//
//  HomeViewController.m
//  location
//
//  Created by Dongxiang Xu on 2024/8/16.
//

#import "HomeViewController.h"
#import "HomeManageViewController.h"
#import "SafeViewController.h"
#import "RegionSettingViewController.h"
#import "XDXBaseTabBarViewController.h"
#import "LoginViewController.h"
#import "XDXMapView.h"
#import "CustomAnnotationView.h"
#import "MapHierarchyView.h"
#import "XDXPointAnnotation.h"
#import "NotifyToast.h"
#import "XDXLocationManager.h"
#import "MemberListView.h"
#import "MemberTrackView.h"
#import "LaunchSOSView.h"
#import "MapSuperView.h"
#import "HomeSheetPopView.h"
#import "InviteView.h"
#import "JoinHomeView.h"
#import "EndSOSView.h"
#import "AddHomeView.h"
#import "MemberTrackDetailViewController.h"
#import "UIImageView+WebCache.h"
#import "WGS84TOGCJ02.h"
#import "StaticTimeScheduler.h"
#import "TrackTool.h"

#define BubbleSide 28.f
API_AVAILABLE(ios(15.0))
@interface HomeViewController ()<MKMapViewDelegate,UIGestureRecognizerDelegate>

@property (nonatomic, strong) FMDatabase *fmdb;
@property (nonatomic, strong) MapSuperView *superView;
@property (nonatomic, strong) UILabel *disconnected;
@property (nonatomic, strong) XDXMapView *mapView;
@property (nonatomic, strong) NSTimer *mapOperationTimer;
@property (nonatomic, strong) NSTimer *mapAnnTimer;
@property (nonatomic, strong) NSObject<MKAnnotation> *foucusAnn; //滑动地图时切换展示的Annotation
@property (nonatomic, strong) UIView *roomView;
@property (nonatomic, strong) UILabel *roomName;
@property (nonatomic, strong) UIImageView *roomImage;
@property (nonatomic, strong) CALayer *roomLayer;
@property (nonatomic, strong) UIImageView *roomSel;
@property (nonatomic, strong) UIButton *add;

//@property (nonatomic, strong) UIButton *menuButton;
//@property (nonatomic, strong) UIButtonConfiguration *config;
@property (nonatomic, strong) UIButton *mapButton;
//@property (nonatomic, strong) UIButton *sosButton;
@property (nonatomic, strong) UIButton *vector;
@property (nonatomic, strong) NSMutableDictionary *locations;

@property (nonatomic, strong) UIView *bgView;
@property (nonatomic, strong) MemberListView *memberListView;
@property (nonatomic, assign) NSInteger netDate;
@property (nonatomic, strong) NSMutableArray *activityArray;
@property (nonatomic, strong) NSMutableArray *tableArray;
@property (nonatomic, strong) MemberTrackView *memberTrackView;
@property (nonatomic, strong) NSMutableDictionary *groupInfo;
@property (nonatomic, strong) UIImageView *left;
@property (nonatomic, strong) UIImageView *right;
@property (nonatomic, assign) CGFloat zoomLevel;
@property (nonatomic, assign) CGFloat originY;

// ---- GPT angular allocator ----
@property (nonatomic, strong) NSObject<MKAnnotation> *detailAnn; //点击个人展示轨迹时的Annotation，地图上不进行缩小
@property (nonatomic, strong) NSMutableArray *groupList; // 全局群组列表
@property (nonatomic, assign) NSInteger leftOffscreenSequence;
@property (nonatomic, assign) NSInteger rightOffscreenSequence;
@property (nonatomic, assign) BOOL leftNeedsSlotResort;
@property (nonatomic, assign) BOOL rightNeedsSlotResort;


@end

@implementation HomeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(syncGroupDataWithMemberList) name:Noti_SyncGroupData object:nil];
    
    self.navigationController.navigationItem.leftItemsSupplementBackButton = NO;
    self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
    UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    backBtn.frame = CGRectMake(0, 0, 44, 44);                     // 控制触摸区域
    [backBtn setImage:[UIImage imageNamed:@"nav_back"] forState:UIControlStateNormal];
    [[backBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        [self.navigationController popViewControllerAnimated:YES];
    }];
    [self.navigationController.navigationBar addSubview:backBtn];
    
    self.view.backgroundColor = RealWhiteColor;
    
    _superView = [[MapSuperView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    [self.view addSubview:_superView];
    
#pragma mark - UI布局代码
    
    self.mapView = [[XDXMapView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.mapView.delegate = self;
    self.mapView.showsUserLocation = YES;
    self.mapView.zoomLevel = 15;
    self.mapView.userTrackingMode = MKUserTrackingModeFollow;
    self.mapView.rotateEnabled = YES;
    self.mapView.showsCompass = NO;
    self.mapView.showsBuildings = YES;
    [_superView addSubview:self.mapView];
    
    UIImageView *topImg = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 120)];
    topImg.image = [UIImage imageNamed:@"home_top"];
    [self.superView addSubview:topImg];
    
    _disconnected = [[UILabel alloc] initWithFrame:CGRectMake(10, STATUSHEIGHT, SCREEN_WIDTH-20, 30)];
    _disconnected.layer.masksToBounds = YES;
    [_disconnected.layer setCornerRadius:10];
    _disconnected.backgroundColor = [RedColor colorWithAlphaComponent:0.3];
    _disconnected.text = @"";
    _disconnected.hidden = YES;
    _disconnected.textAlignment = NSTextAlignmentCenter;
    _disconnected.font = DEFAULT_FONT(15);
    _disconnected.textColor = RedColor;
    [self.view addSubview:_disconnected];
    
    self.roomView = [[UIView alloc] initWithFrame:CGRectMake(16, STATUSHEIGHT+3, 118, 40)];
    [self.view addSubview:self.roomView];
    _roomLayer = [CALayer layer];
    _roomLayer.frame = self.roomView.bounds;
    _roomLayer.cornerRadius = 21;
    _roomLayer.masksToBounds = NO;
    _roomLayer.backgroundColor = RealWhiteColor.CGColor;
    _roomLayer.shadowColor = RealBlackColor.CGColor;
    _roomLayer.shadowOffset = CGSizeMake(0,2);
    _roomLayer.shadowOpacity = 0.1;
    _roomLayer.shadowRadius = 3;
    [self.roomView.layer addSublayer:_roomLayer];
    
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
    [[tap rac_gestureSignal] subscribeNext:^(id x) {
        HomeSheetPopView *view = [[HomeSheetPopView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) StartY:CGRectGetMaxY(self.roomView.frame)+6 TGroupId:[XDXShareInstance shareInstance].groupId IsManage:YES];
        [self.tabBarController.view addSubview:view];
        view.RoomManageBlock = ^{
            HomeManageViewController *vc = [[HomeManageViewController alloc] init];
            [self.navigationController pushViewController:vc animated:YES];
        };
        view.RoomManageClickBlock = ^(NSDictionary *groupInfo) {
            self.groupInfo = [NSMutableDictionary dictionaryWithDictionary:groupInfo];
            [XDXShareInstance shareInstance].groupId = self.groupInfo[@"id"];
            [[NSUserDefaults standardUserDefaults] setValue:self.groupInfo[@"id"] forKey:GroupId];
            [[NSUserDefaults standardUserDefaults] synchronize];
            UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
            [feedBackGenertor impactOccurred];
            [((SafeViewController *)((UINavigationController *)self.tabBarController.childViewControllers.lastObject).visibleViewController) getGroupList];
            [self setRoom];
            [self getGroupInfo];
        };
    }];
    [self.roomView addGestureRecognizer:tap];
    
    self.roomName = [[UILabel alloc] initWithFrame:CGRectMake(16 , 0, self.roomView.width-32, self.roomView.height)];
    self.roomName.textColor = RealBlackColor;
    self.roomName.font = MEDIUM_FONT(16);
    [self.roomView addSubview:self.roomName];
    
    _roomImage = [[UIImageView alloc] initWithFrame:CGRectMake(self.roomName.maxX+4, (self.roomView.height-20)/2, 20, 20)];
    [self.roomView addSubview:_roomImage];
    
    _roomSel = [[UIImageView alloc] initWithFrame:CGRectMake(self.roomView.width-27, (self.roomView.height-12)/2, 12, 12)];
    _roomSel.image = [UIImage imageNamed:@"home_down"];
    [self.roomView addSubview:_roomSel];
    
    self.add = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-56, STATUSHEIGHT+3, 40, 40)];
    [self.view addSubview:self.add];
    [[self.add rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        AddHomeView *addView = [[AddHomeView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        [self.tabBarController.view addSubview:addView];
        addView.AddHomeViewBlock = ^(NSInteger index) {
            if (index==0) {
                InviteView *view = [[InviteView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) GroupInfo:self.groupInfo];
                [self.tabBarController.view addSubview:view];
            }else{
                JoinHomeView *view = [[JoinHomeView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
                [self.tabBarController.view addSubview:view];
            }
        };
    }];
    CALayer *addLayer = [CALayer layer];
    addLayer.frame = self.add.bounds;
    addLayer.cornerRadius = 16;
    addLayer.masksToBounds = NO;
    addLayer.backgroundColor = RealWhiteColor.CGColor;
    addLayer.shadowColor = RealBlackColor.CGColor;
    addLayer.shadowOffset = CGSizeMake(0,2);
    addLayer.shadowOpacity = 0.1;
    addLayer.shadowRadius = 3;
    [self.add.layer addSublayer:addLayer];
    UIImageView *addImg = [[UIImageView alloc] initWithFrame:CGRectMake((self.add.width-22)/2, (self.add.height-22)/2, 22, 22)];
    addImg.image = [UIImage imageNamed:@"home_add"];
    [self.add addSubview:addImg];
    
    //    _menuButton = [UIButton buttonWithType:UIButtonTypeSystem];
    //    if (@available(iOS 15.0, *)) {
    //        _config = [UIButtonConfiguration plainButtonConfiguration];
    //        _config.baseForegroundColor = RealBlackColor;
    //        _config.image = [UIImage imageNamed:@"menu_img"];
    //        _config.imagePlacement = NSDirectionalRectEdgeTrailing;
    //        _config.imagePadding = 4;
    //        _config.contentInsets = NSDirectionalEdgeInsetsMake(0, 20, 0, 12);
    //        UIBackgroundConfiguration *bg = [UIBackgroundConfiguration clearConfiguration];
    //
    //        // 气泡效果的背景配置 - 使用最透明的模糊效果
    //        bg.visualEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemUltraThinMaterialLight]; // 超薄材质,透明度最高
    //        bg.cornerRadius = 24;
    //        _config.background = bg;
    //        _menuButton.configuration = _config;
    //        _menuButton.translatesAutoresizingMaskIntoConstraints = NO;
    //
    //        // 气泡立体感的关键 - 内层高光边框
    //        _menuButton.layer.masksToBounds = NO;
    //        _menuButton.layer.borderColor = [RealWhiteColor colorWithAlphaComponent:0.4].CGColor;
    //        _menuButton.layer.borderWidth = 1.0;  // 内层亮边
    //        _menuButton.layer.cornerRadius = 24;
    //        _menuButton.layer.shadowColor = RealBlackColor.CGColor;
    //        _menuButton.layer.shadowOffset = CGSizeMake(0,2);
    //        _menuButton.layer.shadowOpacity = 0.3;
    //        _menuButton.layer.shadowRadius = 3;
    //    }
    //
    //    [self.menuButton setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    //    [self.menuButton setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    //    [self.menuButton addTarget:self action:@selector(menuButtonTouchDown:forEvent:) forControlEvents:UIControlEventTouchDown];
    //    self.menuButton.showsMenuAsPrimaryAction = YES;
    //    [self.view addSubview:_menuButton];
    //    [NSLayoutConstraint activateConstraints:@[
    //         [self.menuButton.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:(STATUSHEIGHT+7)],
    //         [self.menuButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-12],
    //         [self.menuButton.heightAnchor constraintEqualToConstant:48],
    //     ]];
    
    self.mapButton = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-56, SCREEN_HEIGHT-ORIGIN_H-56, 40, 40)];
    [self.view addSubview:self.mapButton];
    [[self.mapButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        MapHierarchyView *view = [[MapHierarchyView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        [self.tabBarController.view addSubview:view];
        view.MapHierarchyViewBlock = ^(NSInteger index) {
            NSInteger showTraffic = [[[NSUserDefaults standardUserDefaults] objectForKey:ShowTraffic] boolValue];
            NSInteger roadNet = [[[NSUserDefaults standardUserDefaults] objectForKey:RoadNet] boolValue];
            if (index==0) {
                self.mapView.mapType = MKMapTypeStandard;
            }else if (index==1){
                self.mapView.mapType = (showTraffic==0)?(roadNet==0?MKMapTypeSatellite:MKMapTypeHybrid):MKMapTypeHybridFlyover;
            }else if (index==2){
                if (self.mapView.zoomLevel>16.0) {
                    self.mapView.mapType = (showTraffic==0)?(roadNet==0?MKMapTypeSatellite:MKMapTypeHybrid):MKMapTypeHybridFlyover;
                }else{
                    self.mapView.mapType = MKMapTypeStandard;
                }
            }
            self.mapView.showsTraffic = showTraffic;
        };
        view.MapHierarchyDismissBlock = ^{
            [self.memberListView show];
        };
        [self.memberListView dismiss];
    }];
    CALayer *mapButtonLayer = [CALayer layer];
    mapButtonLayer.frame = self.mapButton.bounds;
    mapButtonLayer.cornerRadius = 16;
    mapButtonLayer.masksToBounds = NO;
    mapButtonLayer.backgroundColor = RealWhiteColor.CGColor;
    mapButtonLayer.shadowColor = RealBlackColor.CGColor;
    mapButtonLayer.shadowOffset = CGSizeMake(0,2);
    mapButtonLayer.shadowOpacity = 0.1;
    mapButtonLayer.shadowRadius = 3;
    [self.mapButton.layer addSublayer:mapButtonLayer];
    UIImageView *mapButtonImg = [[UIImageView alloc] initWithFrame:CGRectMake((self.mapButton.width-22)/2, (self.mapButton.height-22)/2, 22, 22)];
    mapButtonImg.image = [UIImage imageNamed:@"map_pop"];
    [self.mapButton addSubview:mapButtonImg];
    
    self.vector = [[UIButton alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-56, self.mapButton.y-56, 40, 40)];
    [self.view addSubview:self.vector];
    [[self.vector rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        if (self.mapView.userLocation.coordinate.latitude>0 && self.mapView.userLocation.coordinate.longitude>0) {
            [UIView animateWithDuration:0.3 animations:^{
                self.vector.alpha = 0;
            }];
            [self.mapView rotateMapToNorthAnimated:YES Coordinate:self.mapView.userLocation.coordinate];
            
            self.foucusAnn = self.mapView.userLocation;
            
            CustomAnnotationView *annView = ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]);
            NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
            [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
            for (XDXPointAnnotation *annotation in self.locations.allValues) {
                CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
                NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
                annView.zPriority = MKAnnotationViewZPriorityMin;
            }
            ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]).zPriority = MKAnnotationViewZPriorityMax;
        }else{
            CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(39.91,116.41);
            [self.mapView rotateMapToNorthAnimated:YES Coordinate:coord];
        }
    }];
    CALayer *vectorLayer = [CALayer layer];
    vectorLayer.frame = self.vector.bounds;
    vectorLayer.cornerRadius = 16;
    vectorLayer.masksToBounds = NO;
    vectorLayer.backgroundColor = RealWhiteColor.CGColor;
    vectorLayer.shadowColor = RealBlackColor.CGColor;
    vectorLayer.shadowOffset = CGSizeMake(0,2);
    vectorLayer.shadowOpacity = 0.1;
    vectorLayer.shadowRadius = 3;
    [self.vector.layer addSublayer:vectorLayer];
    UIImageView *vectorImg = [[UIImageView alloc] initWithFrame:CGRectMake((self.vector.width-22)/2, (self.vector.height-22)/2, 22, 22)];
    vectorImg.image = [UIImage imageNamed:@"back_location"];
    [self.vector addSubview:vectorImg];
    
    //    self.sosButton = [[UIButton alloc] initWithFrame:CGRectMake(5, self.mapButton.y, 62, 62)];
    //    self.sosButton.hidden = YES;
    //    [self.sosButton setBackgroundImage:[UIImage imageNamed:@"sos_nor"] forState:UIControlStateNormal];
    //    [self.view addSubview:self.sosButton];
    //    [[self.sosButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
    //        if (self.sosButton.width<80) {
    //            LaunchSOSView *view = [[LaunchSOSView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) GroupInfo:self.groupInfo];
    //            [self.tabBarController.view addSubview:view];
    //            view.LaunchSOSBlock = ^{
    
    
    // 发送socket，将acticity改为sos
    //                CLLocationCoordinate2D loc = [WGS84TOGCJ02 transformFromWGSToGCJ:[[XDXLocationManager shareInstance].lastLocation coordinate]];
    //                if (@available(iOS 14.0, *)) {
    //                    NSDictionary *dict = @{@"type":@"location_update",@"location":@{@"latitude":[NSString stringWithFormat:@"%f",loc.latitude],@"longitude":[NSString stringWithFormat:@"%f",loc.longitude],@"activity":[XDXLocationManager shareInstance].activityString,@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"nickName":[XDXShareInstance shareInstance].nickName,@"lastLog":[XDXLocationManager shareInstance].lastlog,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0",@"isLocationAuth":([[XDXLocationManager shareInstance].locationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedAlways?@(1):@(0))}};
    //                    [[XDXSocket shareInstance] sendMessage:dict];
    //                }
    //
    //                [self.sosButton setFrame:CGRectMake(5, self.mapButton.y, 122, 62)];
    //                [self.sosButton setBackgroundImage:[UIImage imageNamed:@"sos_sel"] forState:UIControlStateNormal];
    //
    //                // 更新地图上的自己图标为sos的UI
    //                NSDictionary *dic = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":@"0",@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
    //                [self loadCustomAnnotionViewWithDic:dic AnnotionView:((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation])];
    //            };
    //        }else{
    //            EndSOSView *view = [[EndSOSView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) GroupInfo:self.groupInfo];
    //            [self.tabBarController.view addSubview:view];
    //            view.EndSOSBlock = ^{
    
    // 发送socket，将acticity改为activityString
    //                CLLocationCoordinate2D loc = [WGS84TOGCJ02 transformFromWGSToGCJ:[[XDXLocationManager shareInstance].lastLocation coordinate]];
    //                if (@available(iOS 14.0, *)) {
    //                    NSDictionary *dict = @{@"type":@"location_update",@"location":@{@"latitude":[NSString stringWithFormat:@"%f",loc.latitude],@"longitude":[NSString stringWithFormat:@"%f",loc.longitude],@"activity":[XDXLocationManager shareInstance].activityString,@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"nickName":[XDXShareInstance shareInstance].nickName,@"lastLog":[XDXLocationManager shareInstance].lastlog,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0",@"isLocationAuth":([[XDXLocationManager shareInstance].locationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedAlways?@(1):@(0))}};
    //                    [[XDXSocket shareInstance] sendMessage:dict];
    //                }
    //
    //                [self.sosButton setFrame:CGRectMake(5, self.mapButton.y, 62, 62)];
    //                [self.sosButton setBackgroundImage:[UIImage imageNamed:@"sos_nor"] forState:UIControlStateNormal];
    //
    //                // 更新地图上的自己图标为sos的UI
    //                NSDictionary *dic = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":@"0",@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
    //                [self loadCustomAnnotionViewWithDic:dic AnnotionView:((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation])];
    //            };
    //        }
    //    }];
    
    self.superView.unVisibleLocations = [NSMutableDictionary dictionary];
    self.leftOffscreenSequence = 0;
    self.rightOffscreenSequence = 0;
    self.leftNeedsSlotResort = NO;
    self.rightNeedsSlotResort = NO;
    
    __block HomeViewController *selfBlock = self;
    
    self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    self.bgView.backgroundColor = [RealBlackColor colorWithAlphaComponent:0.4];
    self.bgView.alpha = 0;
    [self.view addSubview:self.bgView];
    
    [self loadMemberListView];
    
    
#pragma mark - socket重连之后
    [XDXSocket shareInstance].XDXSocketOpenBlock = ^(BOOL isOpen) {
        if (isOpen) {
            CLLocationCoordinate2D loc = [WGS84TOGCJ02 transformFromWGSToGCJ:[[XDXLocationManager shareInstance].lastLocation coordinate]];
            NSDictionary *dict = @{@"type":@"location_update",@"location":@{@"latitude":[NSString stringWithFormat:@"%f",loc.latitude],@"longitude":[NSString stringWithFormat:@"%f",loc.longitude],@"activity":[XDXLocationManager shareInstance].activityString,@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"nickName":[XDXShareInstance shareInstance].nickName,@"lastLog":[XDXLocationManager shareInstance].lastlog,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0",@"isLocationAuth":([[XDXLocationManager shareInstance].locationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedAlways?@(1):@(0))}};
            [[XDXSocket shareInstance] sendMessage:dict];
            if ([XDXSocket shareInstance].groupId.integerValue != [XDXShareInstance shareInstance].groupId.integerValue && [self.groupInfo[@"userInfo"] isKindOfClass:[NSMutableArray class]]) {
                [[XDXSocket shareInstance] sendMessage:@{@"type":@"group_members_location"}];
            }
        }
    };
    [XDXSocket shareInstance].XDXSocketReceiveBlock = ^(NSDictionary *message) {
        [selfBlock reciveMessage:message];
    };
    
    [XDXLocationManager shareInstance].XDXLocationManagerHeadBlock = ^(CGFloat degree) {
        ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]).heading.transform = CGAffineTransformMakeRotation(degree * M_PI / 180.f );
    };
    
#pragma mark - 自己产生定位Block
    [XDXLocationManager shareInstance].XDXLocationManagerLocationBlock = ^(NSDictionary *dic) {
        if ([XDXShareInstance shareInstance].nickName.length>0) {
            for (int i = 0; i < selfBlock.memberListView.memberList.count; i ++) {
                NSObject *obj = selfBlock.memberListView.memberList[i];
                if ([obj isKindOfClass:[NSMutableDictionary class]] && [((NSDictionary *)obj)[@"userId"] integerValue]==[[XDXShareInstance shareInstance].userId integerValue]){
                    
                    CLLocationCoordinate2D loc = [WGS84TOGCJ02 transformFromWGSToGCJ:[[XDXLocationManager shareInstance].lastLocation coordinate]];
                    [obj setValue:[NSString stringWithFormat:@"%f",loc.latitude] forKey:@"latitude"];
                    [obj setValue:[NSString stringWithFormat:@"%f",loc.longitude] forKey:@"longtitude"];
                    if (dic[@"isLocationAuth"]) {
                        [obj setValue:dic[@"isLocationAuth"] forKey:@"isLocationAuth"];
                    }
                    if (![[XDXLocationManager shareInstance].activityString isEqualToString:@"静止"] || ![((NSDictionary *)obj)[@"activity"] isEqualToString:@"静止"]) {
                        [obj setValue:[XDXLocationManager shareInstance].activityString forKey:@"activity"];
                        [obj setValue:[XDXTimeTool currentDate] forKey:@"timestamp"];
                    }else {
                        [self getStaticStartTimeWithUserId:[XDXShareInstance shareInstance].userId Obj:(NSMutableDictionary *)obj Location:dic[@"location"]];
                    }
                    [obj setValue:[XDXShareInstance shareInstance].nickName forKey:@"nickName"];
                    
                    
                    NSDictionary *region = [self matchRegionsWithStaticPoint:@{@"latitude":((NSMutableDictionary *)obj)[@"latitude"],@"longtitude":((NSMutableDictionary *)obj)[@"longtitude"]}];
                    if (region) {
                        [obj setValue:region[@"name"] forKey:@"lastlog"];
                    }else{
                        [obj setValue:[XDXLocationManager shareInstance].lastlog forKey:@"lastlog"];
                    }
                    [obj setValue:@"0" forKey:@"logout"];
                    [self.memberListView.tableView reloadData];
                    break;
                }
            }
            
            // 检索聚合图标
            [self processAnnotationClustering];
            
            NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
            [self loadCustomAnnotionViewWithDic:dict AnnotionView:((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation])];
        }
    };
    
    {
        UIView *letfView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, self.mapView.height)];
        letfView.tag=50;
        [self.superView addSubview:letfView];
        UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
        panGestureRecognizer.delegate = self;
        [letfView addGestureRecognizer:panGestureRecognizer];
        
        _left = [[UIImageView alloc] initWithFrame:CGRectMake(-18, 0, 18, 126)];
        _left.image = [UIImage imageNamed:@"wave_left"];
        [self.superView addSubview:_left];
    }
    
    {
        UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-20, 0, 20, self.mapView.height)];
        rightView.tag=51;
        [self.superView addSubview:rightView];
        UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
        panGestureRecognizer.delegate = self;
        [rightView addGestureRecognizer:panGestureRecognizer];
        
        _right = [[UIImageView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH, 0, 18, 126)];
        _right.image = [UIImage imageNamed:@"wave_right"];
        [self.superView addSubview:_right];
    }
    
    self.locations = [NSMutableDictionary dictionary];
    // 初始化时从plist文件加载群组列表
    [self loadGroupListFromPlist];
    
    // 加载本地存储的regions数据
    [self loadRegionsFromPlist];
    
    [self getUserInfo];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ReloadNickName) name:Noti_ReloadNickName object:nil];
    
    NSInteger mapType = [[[NSUserDefaults standardUserDefaults] objectForKey:MapType] integerValue];
    BOOL showTraffic = [[[NSUserDefaults standardUserDefaults] objectForKey:ShowTraffic] boolValue];
    NSInteger roadNet = [[[NSUserDefaults standardUserDefaults] objectForKey:RoadNet] boolValue];
    if (mapType==0) {
        self.mapView.mapType = MKMapTypeStandard;
    }else if (mapType==1){
        self.mapView.mapType = (showTraffic==0)?(roadNet==0?MKMapTypeSatellite:MKMapTypeHybrid):MKMapTypeHybridFlyover;
    }else if (mapType==2){
        if (self.mapView.zoomLevel>16.0) {
            self.mapView.mapType = (showTraffic==0)?(roadNet==0?MKMapTypeSatellite:MKMapTypeHybrid):MKMapTypeHybridFlyover;
        }else{
            self.mapView.mapType = MKMapTypeStandard;
        }
    }
    self.mapView.showsTraffic = showTraffic;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:YES animated:NO];
    [((XDXBaseTabBarViewController *)self.tabBarController) xdx_showCustomTabBar];
    if (self.memberTrackView) {
        [((XDXBaseTabBarViewController *)self.tabBarController) xdx_hideCustomTabBar];
    }
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:NO];
    if (self.navigationController.childViewControllers.count>1) {
        [((XDXBaseTabBarViewController *)self.tabBarController) xdx_hideCustomTabBar];
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:Noti_ReloadNickName object:nil];
}

- (void)setRoom
{
    self.roomName.text = [NSString stringWithFormat:@"%@",self.groupInfo[@"name"]];
    [self.roomName sizeToFit];
    if (self.roomName.width>(SCREEN_WIDTH-156)) {
        self.roomName.width = (SCREEN_WIDTH-156);
    }
    [self.roomName setFrame:CGRectMake(18, 0, self.roomName.width, self.roomView.height)];
    if ([self.groupInfo[@"membership"] isKindOfClass:[NSDictionary class]]) {
        [self.roomView setFrame:CGRectMake(16, STATUSHEIGHT+3, self.roomName.width+70, 40)];
        self.roomImage.x = self.roomName.maxX+4;
        if ([self.groupInfo[@"membership"][@"planType"] integerValue]==1) {
            self.roomImage.image = [UIImage imageNamed:@"icon_close"];
        }else if ([self.groupInfo[@"membership"][@"planType"] integerValue]==2) {
            self.roomImage.image = [UIImage imageNamed:@"icon_silver"];
        }else if ([self.groupInfo[@"membership"][@"planType"] integerValue]==3) {
            self.roomImage.image = [UIImage imageNamed:@"icon_gold"];
        }
        
    }else{
        [self.roomView setFrame:CGRectMake(16, STATUSHEIGHT+3, self.roomName.width+54, 40)];
        self.roomImage.image = nil;
    }
    
    self.roomLayer.frame = self.roomView.bounds;
    [self.roomSel setFrame:CGRectMake(self.roomView.width-27, (self.roomView.height-12)/2, 12, 12)];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    CGPoint translation = [recognizer locationInView:recognizer.view];
    if (recognizer.view.tag==50) {
        self.left.centerY = translation.y;
        if (self.left.centerY<=63) {
            self.left.centerY = 63;
        }else if (self.left.centerY>=(self.mapView.height-63)){
            self.left.centerY = (self.mapView.height-63);
        }
        if (translation.x>5) {
            if (_left.x<0) {
                if (self.memberListView.y<(STATUSHEIGHT+5)) {
                    [self.memberListView show];
                }
                UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
                [feedBackGenertor impactOccurred];
                [UIView animateWithDuration:0.2 animations:^{
                    self.left.x = 0;
                }];
            }
        }else{
            if (_left.x>=0) {
                UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
                [feedBackGenertor impactOccurred];
                [UIView animateWithDuration:0.1 animations:^{
                    self.left.x = -18;
                }];
            }
        }
    }else if (recognizer.view.tag==51){
        self.right.centerY = translation.y;
        if (self.right.centerY<=63) {
            self.right.centerY = 63;
        }else if (self.right.centerY>=(self.mapView.height-63)){
            self.right.centerY = (self.mapView.height-63);
        }
        if (translation.x<(SCREEN_WIDTH-5)) {
            if (_right.x>=SCREEN_WIDTH) {
                if (self.memberListView.y<(STATUSHEIGHT+5)) {
                    [self.memberListView show];
                }
                UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
                [feedBackGenertor impactOccurred];
                [UIView animateWithDuration:0.2 animations:^{
                    self.right.x = (SCREEN_WIDTH-18);
                }];
            }
        }else{
            if (_right.x>=(SCREEN_WIDTH-5)) {
                UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
                [feedBackGenertor impactOccurred];
                [UIView animateWithDuration:0.1 animations:^{
                    self.right.x = SCREEN_WIDTH;
                }];
            }
        }
    }
    
    
    if (recognizer.state == UIGestureRecognizerStateBegan){
        _zoomLevel = self.mapView.zoomLevel;
        _originY = translation.y;
        self.mapView.userTrackingMode = MKUserTrackingModeNone;
    }else if (recognizer.state == UIGestureRecognizerStateEnded){
        if (_left.x>=0) {
            UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
            [feedBackGenertor impactOccurred];
            [UIView animateWithDuration:0.1 animations:^{
                self.left.x = -18;
            }];
        }else if (_right.x<(SCREEN_WIDTH-5)){
            UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
            [feedBackGenertor impactOccurred];
            [UIView animateWithDuration:0.1 animations:^{
                self.right.x = SCREEN_WIDTH;
            }];
        }
    }
    
    CGFloat level = _zoomLevel-((recognizer.view.tag==50?self.left:self.right).centerY-_originY)/31.0;
    if (level<2) {
        level=2;
    }else if (level>18){
        level=18;
    }
    
    if (recognizer.view.tag==50 && self.left.x>-1) {
        [self.mapView setZoomLevel:level];
    }else if (recognizer.view.tag==51 && self.right.x<(SCREEN_WIDTH-17)){
        [self.mapView setZoomLevel:level];
    }
}

#pragma mark - 添加成员列表视图，以及处理回调block
- (void)loadMemberListView
{
    __block HomeViewController *selfBlock = self;
    self.memberListView = [[MemberListView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT-STATUSHEIGHT)];
    self.memberListView.map = self.mapButton;
    self.memberListView.vector = self.vector;
    [self.view addSubview:self.memberListView];
    
    // 成员列表视图中点击成员
    self.memberListView.MemberInfoBlock = ^(NSMutableDictionary *info) {
        [selfBlock.memberTrackView dismiss];
        
        if ([info[@"userId"] integerValue] == [XDXShareInstance shareInstance].userId.integerValue) {
            NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
            [selfBlock loadCustomAnnotionViewWithDic:dict AnnotionView:((CustomAnnotationView *)[selfBlock.mapView viewForAnnotation:selfBlock.mapView.userLocation])];
            CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(selfBlock.mapView.userLocation.coordinate.latitude,selfBlock.mapView.userLocation.coordinate.longitude);
            UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
            [feedBackGenertor impactOccurred];
            [selfBlock.mapView rotateMapToNorthAnimated:YES Coordinate:coord];
            __block HomeViewController *selfABlock = selfBlock;
            
            [selfABlock.memberListView dismiss];
            selfABlock.roomView.hidden = YES;
            selfABlock.mapButton.hidden = YES;
            selfABlock.vector.hidden = YES;
            selfABlock.add.hidden = YES;
            //                selfABlock.sosButton.hidden = YES;
            
            selfABlock.tableArray = [NSMutableArray array];
            
            if ([info[@"dates"] isKindOfClass:[NSArray class]] && [info[@"dates"] count]>0 && [[info[@"dates"] firstObject] isEqualToString:[[XDXTimeTool currentDate] substringToIndex:10]]) {
                selfABlock.netDate = 0;
                [selfABlock getMemberInfoWithUserId:info[@"userId"] Date:info[@"dates"][selfABlock.netDate] Success:^(NSArray *data) {
                    [selfABlock readMoreDataWithData:data Info:info];
                    [selfABlock showReloadMemberTrackViewWithInfo:info];
                } Error:^(NSDictionary *data) {
                    [selfABlock showReloadMemberTrackViewWithInfo:info];
                }];
                
            }else{
                NSMutableDictionary *param = [NSMutableDictionary dictionary];
                [param setValue:info[@"userId"] forKey:@"userId"];
                CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
                [manager encryptedPOST:@"/apps/trajectory/dates"
                            parameters:param
                               success:^(NSDictionary *responseObject) {
                    if ([responseObject[@"code"] integerValue]==200 && [responseObject[@"data"] isKindOfClass:[NSArray class]] && [responseObject[@"data"] count]>0) {
                        [info setValue:responseObject[@"data"] forKey:@"dates"];
                        selfABlock.netDate = 0;
                        [selfABlock getMemberInfoWithUserId:info[@"userId"] Date:info[@"dates"][selfABlock.netDate] Success:^(NSArray *data) {
                            [selfABlock readMoreDataWithData:data Info:info];
                            [selfABlock showReloadMemberTrackViewWithInfo:info];
                        } Error:^(NSDictionary *data) {
                            [selfABlock showReloadMemberTrackViewWithInfo:info];
                        }];
                    }
                }
                               failure:^(NSError *aError) {
                    
                }];
            }
            
            [selfABlock showReloadMemberTrackViewWithInfo:info];
            
            selfABlock.detailAnn = selfABlock.mapView.userLocation;
            selfABlock.foucusAnn =  selfABlock.mapView.userLocation;
            
            for (XDXPointAnnotation *annotation in selfABlock.locations.allValues) {
                CustomAnnotationView *annView = (CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:annotation];
                NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                [selfABlock loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
                
                annView.zPriority = MKAnnotationViewZPriorityMin;
            }
            ((CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:selfABlock.mapView.userLocation]).zPriority = MKAnnotationViewZPriorityMin;
            
            CustomAnnotationView *annView = ((CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:selfABlock.detailAnn]);
            annView.zPriority = MKAnnotationViewZPriorityMax;
            NSDictionary *aDict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
            [selfABlock loadCustomAnnotionViewWithDic:aDict AnnotionView:(CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:selfABlock.mapView.userLocation]];
            [annView xdx_resetCorToDefault];
            
        }else{
            XDXPointAnnotation *annotation = selfBlock.locations[[NSString stringWithFormat:@"%@",info[@"userId"]]];
            CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(annotation.coordinate.latitude,annotation.coordinate.longitude);
            UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
            [feedBackGenertor impactOccurred];
            [selfBlock.mapView rotateMapToNorthAnimated:YES Coordinate:coord];
            __block HomeViewController *selfABlock = selfBlock;
            [selfABlock.memberListView dismiss];
            selfABlock.roomView.hidden = YES;
            selfABlock.mapButton.hidden = YES;
            selfABlock.vector.hidden = YES;
            selfABlock.add.hidden = YES;
            //                selfABlock.sosButton.hidden = YES;
            
            selfABlock.tableArray = [NSMutableArray array];
            if ([info[@"dates"] isKindOfClass:[NSArray class]] && [info[@"dates"] count]>0 && [[info[@"dates"] firstObject] isEqualToString:[[XDXTimeTool currentDate] substringToIndex:10]]) {
                selfABlock.netDate = 0;
                [selfABlock getMemberInfoWithUserId:info[@"userId"] Date:info[@"dates"][selfABlock.netDate] Success:^(NSArray *data) {
                    [selfABlock readMoreDataWithData:data Info:info];
                    [selfABlock showReloadMemberTrackViewWithInfo:info];
                } Error:^(NSDictionary *data) {
                    [selfABlock showReloadMemberTrackViewWithInfo:info];
                }];
            }else{
                NSMutableDictionary *param = [NSMutableDictionary dictionary];
                [param setValue:info[@"userId"] forKey:@"userId"];
                CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
                [manager encryptedPOST:@"/apps/trajectory/dates"
                            parameters:param
                               success:^(NSDictionary *responseObject) {
                    if ([responseObject[@"code"] integerValue]==200 && [responseObject[@"data"] isKindOfClass:[NSArray class]] && [responseObject[@"data"] count]>0) {
                        [info setValue:responseObject[@"data"] forKey:@"dates"];
                        selfABlock.netDate = 0;
                        [selfABlock getMemberInfoWithUserId:info[@"userId"] Date:info[@"dates"][selfABlock.netDate] Success:^(NSArray *data) {
                            [selfABlock readMoreDataWithData:data Info:info];
                            [selfABlock showReloadMemberTrackViewWithInfo:info];
                        } Error:^(NSDictionary *data) {
                            [selfABlock showReloadMemberTrackViewWithInfo:info];
                        }];
                    }
                }
                               failure:^(NSError *aError) {
                    
                }];
            }
            [selfABlock showReloadMemberTrackViewWithInfo:info];
            
            CustomAnnotationView *annView = ((CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:selfABlock.detailAnn]);
            annView.zPriority = MKAnnotationViewZPriorityMax;
            [annView xdx_resetCorToDefault];
            selfBlock.detailAnn = annotation;
            selfBlock.foucusAnn =  annotation;
            
            for (XDXPointAnnotation *annotation in selfABlock.locations.allValues) {
                CustomAnnotationView *annView = (CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:annotation];
                NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                [selfABlock loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
                
                annView.zPriority = MKAnnotationViewZPriorityMin;
            }
            ((CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:selfABlock.mapView.userLocation]).zPriority = MKAnnotationViewZPriorityMin;
            
            CustomAnnotationView *annoView = ((CustomAnnotationView *)[selfABlock.mapView viewForAnnotation:selfABlock.detailAnn]);
            annView.zPriority = MKAnnotationViewZPriorityMax;
            NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
            [selfABlock loadCustomAnnotionViewWithDic:dict AnnotionView:annoView];
        }
    };
    // 成员列表视图滑动至最顶端或最底端时调用
    self.memberListView.MemberListViewIsTop = ^(CGFloat y) {
        [UIView animateWithDuration:0.3 animations:^{
            if (y<(STATUSHEIGHT+10)) {
                selfBlock.bgView.alpha = 1;
            }else{
                selfBlock.bgView.alpha = 0;
            }
        } completion:^(BOOL finished) {
            if (y<(STATUSHEIGHT+10)) {
                [selfBlock.memberListView.tableView reloadData];
            }
        }];
    };
    
    self.memberListView.MemberFooterBlock = ^(NSInteger index) {
        if (index==0) {
            InviteView *view = [[InviteView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) GroupInfo:selfBlock.groupInfo];
            [selfBlock.tabBarController.view addSubview:view];
        }else if (index==1){
            RegionSettingViewController *vc = [[RegionSettingViewController alloc] init];
            vc.groupInfo = selfBlock.groupInfo;
            [selfBlock.navigationController pushViewController:vc animated:YES];
            vc.RegionSettingBlock = ^{
                [selfBlock getLocationNotificatoins];
            };
        }
    };
    
    self.memberListView.MemberLocationBlock = ^(NSMutableDictionary *location) {
        RegionSettingViewController *vc = [[RegionSettingViewController alloc] init];
        vc.groupInfo = selfBlock.groupInfo;
        vc.locationInfo = location;
        [selfBlock.navigationController pushViewController:vc animated:YES];
        vc.RegionSettingBlock = ^{
            [selfBlock getLocationNotificatoins];
        };
    };
}

- (void)getStaticStartTimeWithUserId:(NSString *)userId
                                 Obj:(NSMutableDictionary *)obj
                            Location:(NSDictionary *)location
{
    [[StaticTimeScheduler shared] enqueueWithUserId:((NSMutableDictionary *)obj)[@"userId"]
                                           location:location
                                             worker:^(NSString *uid, NSDictionary *loc, void (^complete)(NSString * _Nullable)) {
        NSString *today = [[XDXTimeTool currentDate] substringToIndex:10];
        [self getMemberInfoWithUserId:uid Date:today Success:^(NSArray *data) {
            [TrackTool getStaticStartTimeWithData:data Date:today Yestoday:^(NSString *time) {
                if (time) {
                    if ([time containsString:@"&"] || time.length==0) {
                        NSInteger yesTs = [XDXTimeTool getNowTimeTimestamp].integerValue - 86400;
                        NSDate *y = [NSDate dateWithTimeIntervalSince1970:yesTs];
                        NSDateFormatter *f = [[NSDateFormatter alloc] init];
                        [f setDateFormat:@"yyyy-MM-dd"];
                        NSString *yesDateStr = [f stringFromDate:y];
                        
                        NSString *yeTime = @"";
                        if ([time containsString:@"&"]) {
                            yeTime = [time substringFromIndex:1];
                        }
                        
                        [self getMemberInfoWithUserId:uid Date:yesDateStr Success:^(NSArray *data2) {
                            [TrackTool getStaticStartTimeWithData:data2 Date:yesDateStr Yestoday:^(NSString *time2) {
                                if (time2 && time2.length>0) {
                                    complete(time2);
                                } else {
                                    complete(yeTime);
                                }
                            }];
                        } Error:^(id err2) {
                            complete(yeTime);
                        }];
                    } else {
                        complete(time);
                    }
                } else {
                    complete(loc[@"timestamp"]);
                }
            }];
        } Error:^(id err) {
            complete(loc[@"timestamp"]);
        }];
    } apply:^(NSString *startTime) {
        if (startTime.length>0) {
            [(NSMutableDictionary *)obj setValue:startTime forKey:@"timestamp"];
            
            NSDictionary *region = [self matchRegionsWithStaticPoint:@{@"latitude":((NSMutableDictionary *)obj)[@"latitude"],@"longtitude":((NSMutableDictionary *)obj)[@"longtitude"]}];
            if (region) {
                [obj setValue:region[@"name"] forKey:@"lastlog"];
            }else{
                [(NSMutableDictionary *)obj setValue:location[@"lastLog"] forKey:@"lastlog"];
            }
        }
        
        [self.memberListView.tableView reloadData];
    }];
}

// 获取用户当天轨迹
- (void)getMemberInfoWithUserId:(NSString *)userId
                           Date:(NSString *)date
                        Success:(void (^)(id _Nullable))success
                          Error:(void (^)(id _Nullable))error
{
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    [param setValue:userId forKey:@"userId"];
    [param setValue:date forKey:@"date"];
    [param setValue:[XDXShareInstance shareInstance].groupId forKey:@"groupId"];
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentsDirectory = paths.firstObject;
    NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@.plist",userId,date]];
    NSFileManager *fileManager = [[NSFileManager  alloc] init];
    // 如果为今天直接请求，如果为过去日期则先看有没有缓存
    if (![date isEqualToString:[[XDXTimeTool currentDate] substringToIndex:10]]) {
        if ([fileManager fileExistsAtPath:plistPath]){
            NSArray *loadedArray = [NSArray arrayWithContentsOfFile:plistPath];
            if (loadedArray && loadedArray.count>0) {
                success(loadedArray);
                return;
            }
            
        }
    }
    CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
    [manager encryptedPOST:@"/apps/trajectory/daily"
                parameters:param
                   success:^(NSDictionary *responseObject) {
        if ([responseObject[@"code"] integerValue]==200 && [responseObject[@"data"] isKindOfClass:[NSArray class]] && ([responseObject[@"data"] count]>0 || [date isEqualToString:[[XDXTimeTool currentDate] substringToIndex:10]])) {
            NSArray *array = [NSArray arrayWithArray:responseObject[@"data"]];
            if (![date isEqualToString:[[XDXTimeTool currentDate] substringToIndex:10]]) {
                BOOL succ = [array writeToFile:plistPath atomically:YES];
            }
            success(responseObject[@"data"]);
        }else{
            error(responseObject);
        }
    }
                   failure:^(NSError *aError) {
        error(aError);
    }];
}

#pragma mark - 处理接收的socket消息
- (void)reciveMessage:(NSDictionary *)message
{
    if ([message[@"type"] isEqualToString:@"location_update"]) {
        [[HCToast shareInstance] showToast:[NSString stringWithFormat:@"%@位置 更新",message[@"location"][@"nickName"]]];
        if ([message[@"userId"] integerValue] != [XDXShareInstance shareInstance].userId.integerValue && [message[@"location"] isKindOfClass:[NSDictionary class]]) {
            NSMutableDictionary *location = [NSMutableDictionary dictionaryWithDictionary:message[@"location"]];
            
            // 新加入用户发出的socket
            if ([message[@"userId"] isKindOfClass:[NSNull class]] || !self.locations[[NSString stringWithFormat:@"%@",message[@"userId"]]]){
                BOOL needAdd = YES;
                for (int i = 0; i < self.memberListView.memberList.count; i ++) {
                    NSObject *obj = self.memberListView.memberList[i];
                    if ([obj isKindOfClass:[NSMutableDictionary class]] && [((NSDictionary *)obj)[@"userId"] integerValue]==[message[@"userId"] integerValue]){
                        needAdd = NO;
                        if (location[@"latitude"]) {
                            [obj setValue:location[@"latitude"] forKey:@"latitude"];
                        }
                        if (location[@"longitude"]) {
                            [obj setValue:location[@"longitude"] forKey:@"longtitude"];
                        }
                        if (location[@"nickName"] && [location[@"nickName"] length]>0) {
                            [obj setValue:location[@"nickName"] forKey:@"nickName"];
                        }
                        if (location[@"isLocationAuth"]) {
                            [obj setValue:location[@"isLocationAuth"] forKey:@"isLocationAuth"];
                        }
                        if (location[@"activity"]) {
                            [obj setValue:location[@"activity"] forKey:@"activity"];
                            if ([location[@"activity"] isEqualToString:@"静止"]) {
                                [self getStaticStartTimeWithUserId:((NSMutableDictionary *)obj)[@"userId"] Obj:(NSMutableDictionary *)obj Location:location];
                            }else{
                                if (location[@"timestamp"]) {
                                    [obj setValue:location[@"timestamp"] forKey:@"timestamp"];
                                }
                                if (location[@"lastLog"]) {
                                    NSDictionary *region = [self matchRegionsWithStaticPoint:@{@"latitude":((NSMutableDictionary *)obj)[@"latitude"],@"longtitude":((NSMutableDictionary *)obj)[@"longtitude"]}];
                                    if (region) {
                                        [obj setValue:region[@"name"] forKey:@"lastlog"];
                                    }else{
                                        [obj setValue:location[@"lastLog"] forKey:@"lastlog"];
                                    }
                                }
                            }
                        }
                        if (location[@"battery"]) {
                            [obj setValue:location[@"battery"] forKey:@"battery"];
                        }
                        
                        [obj setValue:@"0" forKey:@"logout"];
                        [self.memberListView.tableView reloadData];
                        
                        // 同步更新群组数据
                        [self syncGroupDataWithMemberList];
                        break;
                    }
                }
                if (needAdd) {
                    [self getGroupInfo];
                }
            }else{
                if ([message[@"location"] isKindOfClass:[NSDictionary class]]) {
                    NSMutableDictionary *location = [NSMutableDictionary dictionaryWithDictionary:message[@"location"]];
                    for (int i = 0; i < self.memberListView.memberList.count; i ++) {
                        NSObject *obj = self.memberListView.memberList[i];
                        if ([obj isKindOfClass:[NSMutableDictionary class]] && [((NSDictionary *)obj)[@"userId"] integerValue]==[message[@"userId"] integerValue]){
                            if (location[@"latitude"]) {
                                [obj setValue:location[@"latitude"] forKey:@"latitude"];
                            }
                            if (location[@"longitude"]) {
                                [obj setValue:location[@"longitude"] forKey:@"longtitude"];
                            }
                            if (location[@"nickName"] && [location[@"nickName"] length]>0) {
                                [obj setValue:location[@"nickName"] forKey:@"nickName"];
                            }
                            if (location[@"isLocationAuth"]) {
                                [obj setValue:location[@"isLocationAuth"] forKey:@"isLocationAuth"];
                            }
                            if (location[@"activity"]) {
                                [obj setValue:location[@"activity"] forKey:@"activity"];
                                if ([location[@"activity"] isEqualToString:@"静止"]) {
                                    [self getStaticStartTimeWithUserId:((NSMutableDictionary *)obj)[@"userId"] Obj:(NSMutableDictionary *)obj Location:location];
                                }else{
                                    if (location[@"timestamp"]) {
                                        [obj setValue:location[@"timestamp"] forKey:@"timestamp"];
                                    }
                                    if (location[@"lastLog"]) {
                                        NSDictionary *region = [self matchRegionsWithStaticPoint:@{@"latitude":((NSMutableDictionary *)obj)[@"latitude"],@"longtitude":((NSMutableDictionary *)obj)[@"longtitude"]}];
                                        if (region) {
                                            [obj setValue:region[@"name"] forKey:@"lastlog"];
                                        }else{
                                            [obj setValue:location[@"lastLog"] forKey:@"lastlog"];
                                        }
                                    }
                                }
                            }
                            if (location[@"battery"]) {
                                [obj setValue:location[@"battery"] forKey:@"battery"];
                            }
                            
                            
                            [location setValue:((NSDictionary *)obj)[@"avatar"] forKey:@"avatar"];
                            [obj setValue:@"0" forKey:@"logout"];
                            [self.memberListView.tableView reloadData];
                            
                            break;
                        }
                    }
                    
                    // 移动家人地图中的定位
                    CLLocationCoordinate2D coord = CLLocationCoordinate2DMake([location[@"latitude"] doubleValue],[location[@"longitude"] doubleValue]);
                    XDXPointAnnotation *annotation = self.locations[[NSString stringWithFormat:@"%@",message[@"userId"]]];
                    [annotation setCoordinate:coord];
                    
                    if (location[@"speed"]) {
                        annotation.speed = location[@"speed"];
                    }
                    if (location[@"battery"]) {
                        annotation.battery = location[@"battery"];
                    }
                    if (location[@"activity"]) {
                        annotation.activity = location[@"activity"];
                    }
                    if (location[@"isCharge"]) {
                        annotation.isCharge = location[@"isCharge"];
                    }
                    if (location[@"avatar"]) {
                        annotation.avatar = location[@"avatar"];
                    }
                    // 检索聚合图标
                    [self processAnnotationClustering];
                    // 更新家人在地图中定位的UI
                    [self loadCustomAnnotionViewWithDic:location AnnotionView:((CustomAnnotationView *)[self.mapView viewForAnnotation:annotation])];
                }
                
            }
        }
    }else if ([message[@"type"] isEqualToString:@"group_members_location"]){
        
        [[HCToast shareInstance] showToast:@"响应了group_members_location"];
        [XDXSocket shareInstance].groupId = message[@"groupId"];
        
        // 先移除地图中的成员
        [self clearAnnotaion];
        
        for (NSMutableDictionary *dic in self.memberListView.memberList) {
            for (NSDictionary *obj in message[@"members"]) {
                if ([dic[@"userId"] integerValue]==[obj[@"userId"] integerValue]) {
                    [dic setValue:obj[@"location"][@"activity"] forKey:@"activity"];
                    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                    dateFormatter.locale = [NSLocale systemLocale];
                    dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
                    NSDate *firstDate = [dateFormatter dateFromString:[[obj[@"location"][@"timestamp"] substringToIndex:19] stringByReplacingOccurrencesOfString:@"T" withString:@" "]];
                    NSInteger firstSecond = [firstDate timeIntervalSince1970];
                    NSInteger lastSecond = [[XDXTimeTool getNowTimeTimestamp] integerValue];
                    // 判断是否2天不更新
                    if (lastSecond-firstSecond>=LOGOUT_DURATION) {
                        [dic setValue:@"1" forKey:@"logout"];
                        [dic setValue:obj[@"location"][@"timestamp"] forKey:@"timestamp"];
                    }else{
                        if ([obj[@"location"][@"activity"] isEqualToString:@"静止"]) {
                            [self getStaticStartTimeWithUserId:dic[@"userId"] Obj:dic Location:obj[@"location"]];
                        }else{
                            // 最后一次运动状态超过90s，则视为静止
                            if (lastSecond-firstSecond>=ABNORMAL_DURATION) {
                                [self getStaticStartTimeWithUserId:dic[@"userId"] Obj:dic Location:obj[@"location"]];
                            }else{
                                if (obj[@"location"][@"timestamp"]) {
                                    [dic setValue:obj[@"location"][@"timestamp"] forKey:@"timestamp"];
                                    
                                    NSDictionary *region = [self matchRegionsWithStaticPoint:@{@"latitude":((NSMutableDictionary *)obj)[@"location"][@"latitude"],@"longtitude":((NSMutableDictionary *)obj)[@"location"][@"longitude"]}];
                                    if (region) {
                                        [dic setValue:region[@"name"] forKey:@"lastlog"];
                                    }else{
                                        [dic setValue:obj[@"location"][@"lastLog"] forKey:@"lastlog"];
                                    }
                                }
                            }
                        }
                    }
                    [dic setValue:obj[@"location"][@"isLocationAuth"] forKey:@"isLocationAuth"];
                    [dic setValue:obj[@"location"][@"latitude"] forKey:@"latitude"];
                    [dic setValue:obj[@"location"][@"longitude"] forKey:@"longtitude"];
                    
                    
                    // 添加新用户时，只需要添加地图中没有添加过的新用户，其余用户不用添加
                    if ([dic[@"userId"] integerValue]!=[XDXShareInstance shareInstance].userId.integerValue && !self.locations[[NSString stringWithFormat:@"%@",obj[@"userId"]]]) {
                        [self addAnnotationWithInfo:dic];
                    }
                }
            }
        }
        
        [self syncGroupDataWithMemberList];
        self.detailAnn = nil;
        CustomAnnotationView *annView = ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]);
        NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
        [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
        for (XDXPointAnnotation *annotation in self.locations.allValues) {
            CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
            NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
            [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
        }
        
        
        // 为了刷出边缘头像
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self.mapView setCenterCoordinate:self.mapView.userLocation.coordinate animated:YES];
        });
        
        [self getLocationNotificatoins];
        if (self.memberListView.memberList.count>0) {
            [self.memberListView.tableView setContentOffset:CGPointMake(0, 1)];
        }
        [self.memberListView.tableView reloadData];
        
        // 检索聚合图标
        [self processAnnotationClustering];
    }
}

- (void)logout
{
    self.mapView.delegate = nil;
    self.mapView = nil;
    
    [[XDXSocket shareInstance] close];
    
    [XDXShareInstance shareInstance].userId = @"";
    [XDXShareInstance shareInstance].nickName = @"";
    [XDXShareInstance shareInstance].access_token = @"";
    [XDXShareInstance shareInstance].xg_token = @"";
    
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:UserId];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:AccessToken];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:NickName];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:Avatar];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:ShowTraffic];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:RoadNet];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:MapType];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:GroupId];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:GroupListTime];
    [[NSUserDefaults standardUserDefaults] synchronize];
    [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:LastRegionSendTime];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    [[XDXLocationManager shareInstance].locationManager stopUpdatingHeading];
    [[XDXLocationManager shareInstance].locationManager stopUpdatingLocation];
    [[XDXLocationManager shareInstance].locationManager stopMonitoringSignificantLocationChanges];
    [[XDXLocationManager shareInstance].locationManager stopMonitoringVisits];
    
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"GroupList.plist"];
        // 删除plist文件
        NSFileManager *fileManager = [NSFileManager defaultManager];
        if ([fileManager fileExistsAtPath:plistPath]) {
            [fileManager removeItemAtPath:plistPath error:nil];
        }
    }
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"Regions.plist"];
        // 删除plist文件
        NSFileManager *fileManager = [NSFileManager defaultManager];
        if ([fileManager fileExistsAtPath:plistPath]) {
            [fileManager removeItemAtPath:plistPath error:nil];
        }
    }
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"driveLog.plist"];
        // 删除plist文件
        NSFileManager *fileManager = [NSFileManager defaultManager];
        if ([fileManager fileExistsAtPath:plistPath]) {
            [fileManager removeItemAtPath:plistPath error:nil];
        }
    }
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"regionLog.plist"];
        // 删除plist文件
        NSFileManager *fileManager = [NSFileManager defaultManager];
        if ([fileManager fileExistsAtPath:plistPath]) {
            [fileManager removeItemAtPath:plistPath error:nil];
        }
    }
    
    LoginViewController *vc = [[LoginViewController alloc] init];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
    [UIApplication sharedApplication].keyWindow.rootViewController = nav;
    [[UIApplication sharedApplication].keyWindow makeKeyAndVisible];
}

- (void)ReloadNickName
{
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
    [manager encryptedPOST:@"/system/user/getInfo"
                parameters:param
                   success:^(NSDictionary *responseObject) {
        if ([responseObject[@"code"] integerValue]==200 && [responseObject[@"data"][@"nickName"] isKindOfClass:[NSString class]] && [responseObject[@"data"][@"nickName"] length]>0) {
            [[NSUserDefaults standardUserDefaults] setValue:responseObject[@"data"][@"nickName"] forKey:NickName];
            [[NSUserDefaults standardUserDefaults] synchronize];
            
            for (NSMutableDictionary *obj in self.memberListView.memberList) {
                if ([obj[@"userId"] integerValue] == [XDXShareInstance shareInstance].userId.integerValue) {
                    [obj setValue:responseObject[@"data"][@"nickName"] forKey:@"nickName"];
                }
            }
            [self.memberListView.tableView reloadData];
        }
    }
                   failure:^(NSError *aError) {
        
    }];
}

#pragma mark - 网络请求
- (void)getGroupListSuccess:(void (^)(id _Nullable))success
                      Error:(void (^)(id _Nullable))error
{
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
    [manager encryptedPOST:@"/system/group/grouplist"
                parameters:param
                   success:^(NSDictionary *responseObject) {
        if ([responseObject[@"code"] integerValue]==200 ) {
            // 智能更新群组列表
            [self smartUpdateGroupListWithResponseData:responseObject[@"data"]];
            if ([responseObject[@"data"] count]>0) {
                NSString *groupId = [[NSUserDefaults standardUserDefaults] objectForKey:GroupId];
                BOOL isFoundGroup = NO;
                if (groupId.integerValue>0) {
                    for (NSDictionary *group in self.groupList) {
                        if ([group[@"id"] integerValue] == groupId.integerValue) {
                            isFoundGroup = YES;
                            self.groupInfo = [NSMutableDictionary dictionaryWithDictionary:group];
                            [XDXShareInstance shareInstance].groupId = self.groupInfo[@"id"];
                            [[NSUserDefaults standardUserDefaults] setValue:self.groupInfo[@"id"] forKey:GroupId];
                            [[NSUserDefaults standardUserDefaults] synchronize];
                            [self setRoom];
                            [self getGroupInfo];
                        }
                    }
                }
                if (isFoundGroup==NO || groupId.integerValue==0){
                    NSDictionary *info = self.groupList.firstObject;
                    self.groupInfo = [NSMutableDictionary dictionaryWithDictionary:info];
                    [XDXShareInstance shareInstance].groupId = self.groupInfo[@"id"];
                    [[NSUserDefaults standardUserDefaults] setValue:self.groupInfo[@"id"] forKey:GroupId];
                    [[NSUserDefaults standardUserDefaults] synchronize];
                    [self setRoom];
                    [self getGroupInfo];
                    
                }
            }
            if (success) {
                success(self.groupList);
            }
        }else{
            if (error) {
                error(responseObject);
            }
        }
        [XDXShareInstance shareInstance].ReloadGroupListFlag = NO;
    }
                   failure:^(NSError *aError) {
        if (error) {
            error(aError);
        }
    }];
}

- (void)getGroupInfo
{
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    [param setValue:[XDXShareInstance shareInstance].groupId forKey:@"groupId"];
    CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
    [manager encryptedPOST:@"/system/group/userinfo"
                parameters:param
                   success:^(NSDictionary *responseObject) {
        if ([responseObject[@"code"] integerValue]==200 ) {
            // 清除地图边缘的头像
            for (XDXPointAnnotation *annotation in self.locations.allValues) {
                [((UIView *)self.superView.unVisibleLocations[annotation.userId][@"view"]) removeFromSuperview];
                [self.superView.unVisibleLocations removeObjectForKey:[NSString stringWithFormat:@"%@",annotation.userId]];
            }
            self.leftOffscreenSequence = 0;
            self.rightOffscreenSequence = 0;
            self.leftNeedsSlotResort = NO;
            self.rightNeedsSlotResort = NO;
            // 处理除自己以外的成员信息
            NSMutableArray *userInfo = [NSMutableArray array];
            NSMutableArray *array = [NSMutableArray array];
            for (NSDictionary *user in responseObject[@"data"][@"userInfo"]) {
                if ([user[@"userId"] integerValue] != [XDXShareInstance shareInstance].userId.integerValue) {
                    NSMutableDictionary *aUser = [NSMutableDictionary dictionaryWithDictionary:user];
                    [aUser setValue:@"4" forKey:@"code"];
                    [userInfo addObject:aUser];
                }
                NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:user];
                [array addObject:dic];
            }
            // 智能更新成员列表
            [self smartUpdateMemberListWithResponseData:array];
            self.memberListView.groupInfo = self.groupInfo;
            // groupInfo中添加除自己以外的成员信息
            [self.groupInfo setValue:userInfo forKey:@"userInfo"];
            [[XDXSocket shareInstance] sendMessage:@{@"type":@"group_members_location"}];
        }
        
    }
                   failure:^(NSError *aError) {
        
    }];
}

- (void)clearAnnotaion
{
    self.mapView.selectedAnnotations = @[];
    for (XDXPointAnnotation *annotation in self.locations.allValues) {
        dispatch_async(dispatch_get_main_queue(), ^{
            CustomAnnotationView *annotationView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
            [annotationView.view setFrame:CGRectMake((kWidth-kPortraitWidth)/2, 0, 0, 0)];
            annotationView.viewLayer.frame = annotationView.view.bounds;
            [annotationView.portraitImageView.layer setBorderColor:RealWhiteColor.CGColor];
            annotationView.portraitImageView.layer.cornerRadius = 0;
            [annotationView.portraitImageView setFrame:CGRectMake(kWidth/2, kPortraitHeight, 0, 0)];
            [self.mapView removeAnnotation:annotation];
        });
    }
    [self.locations removeAllObjects];
    
    NSDictionary *offscreenSnapshot = [self.superView.unVisibleLocations copy];
    for (NSString *userId in offscreenSnapshot.allKeys) {
        NSDictionary *info = offscreenSnapshot[userId];
        UIView *view = info[@"view"];
        if ([view isKindOfClass:[UIView class]]) {
            [view removeFromSuperview];
        }
    }
    [self.superView.unVisibleLocations removeAllObjects];
    self.leftOffscreenSequence = 0;
    self.rightOffscreenSequence = 0;
    self.leftNeedsSlotResort = NO;
    self.rightNeedsSlotResort = NO;
}

- (void)getLocationNotificatoins
{
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    [param setValue:[XDXShareInstance shareInstance].groupId forKey:@"groupId"];
    CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
    [manager encryptedPOST:@"/system/group/locationnotificatoins"
                parameters:param
                   success:^(NSDictionary *responseObject) {
        if ([responseObject[@"code"] integerValue]==200) {
            self.memberListView.regions = [NSMutableArray array];
            for (NSDictionary *dic in responseObject[@"data"]) {
                NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:dic];
                [dict setValue:self.groupInfo[@"adminId"] forKey:@"groupAdminId"];
                NSMutableArray *array = [NSMutableArray array];
                BOOL isLaunch = NO;
                for (NSDictionary *user in dic[@"usersNotification"]) {
                    NSMutableDictionary *aUser = [NSMutableDictionary dictionaryWithDictionary:user];
                    [array addObject:aUser];
                    if ([aUser[@"code"] integerValue]!=4) {
                        isLaunch = YES;
                    }
                }
                [dict setValue:array forKey:@"usersNotification"];
                [dict setValue:@(isLaunch) forKey:@"isLaunch"];
                [self.memberListView.regions addObject:dict];
            }
            // 保存regions到本地plist文件
            [self saveRegionsToPlist];
            [self.memberListView.tableView reloadData];
        }
    }
                   failure:^(NSError *aError) {
        
    }];
}

- (void)getUserInfo
{
    NSLog(@"%@",[XDXShareInstance shareInstance].access_token);
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
    [manager encryptedPOST:@"/system/user/getInfo"
                parameters:param
                   success:^(NSDictionary *responseObject) {
        if ([responseObject[@"code"] integerValue]==200 && [responseObject[@"data"][@"nickName"] isKindOfClass:[NSString class]] && [responseObject[@"data"][@"nickName"] length]>0) {
            [[NSUserDefaults standardUserDefaults] setValue:responseObject[@"data"][@"nickName"] forKey:NickName];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [[NSUserDefaults standardUserDefaults] setValue: responseObject[@"data"][@"userId"] forKey:UserId];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [[NSUserDefaults standardUserDefaults] setValue: responseObject[@"data"][@"avatar"] forKey:Avatar];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [XDXShareInstance shareInstance].nickName = responseObject[@"data"][@"nickName"];
            [XDXShareInstance shareInstance].avatar = responseObject[@"data"][@"avatar"];
            [XDXShareInstance shareInstance].userId = responseObject[@"data"][@"userId"];
            [XDXSocket shareInstance].userId = [XDXShareInstance shareInstance].userId;
            [self getVersion];
            [self uploadDeviceToken];
            [self getGroupListSuccess:nil Error:nil];
            
            NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
            [self loadCustomAnnotionViewWithDic:dict AnnotionView:((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation])];
        }else{
            if ([responseObject[@"code"] integerValue]==401) {
                [self logout];
            }else if ([[[NSUserDefaults standardUserDefaults] objectForKey:UserId] integerValue]>0){
                [XDXShareInstance shareInstance].userId = [[NSUserDefaults standardUserDefaults] objectForKey:UserId];
                [XDXSocket shareInstance].userId = [XDXShareInstance shareInstance].userId;
            }
        }
    }
                   failure:^(NSError *aError) {
        if ([[[NSUserDefaults standardUserDefaults] objectForKey:UserId] integerValue]>0){
            [XDXShareInstance shareInstance].userId = [[NSUserDefaults standardUserDefaults] objectForKey:UserId];
            [XDXSocket shareInstance].userId = [XDXShareInstance shareInstance].userId;
        }
    }];
}

#pragma mark - 上传用户推送的token
- (void)uploadDeviceToken
{
    if ([XDXShareInstance shareInstance].xg_token.length>0) {
        NSMutableDictionary *param = [NSMutableDictionary dictionary];
        [param setValue:[XDXShareInstance shareInstance].xg_token forKey:@"token"];
        [param setValue:@(1) forKey:@"deviceType"];
        CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
        [manager encryptedPOST:@"/apps/data/uploadtoken"
                    parameters:param
                       success:^(NSDictionary *responseObject) {
            
        }
                       failure:^(NSError *aError) {
            
        }];
    }
}

#pragma mark - 轨迹数据处理
- (void)readMoreDataWithData:(NSArray *)data Info:(NSDictionary *)info
{
    NSMutableArray *array = [NSMutableArray array];
    NSMutableDictionary *tempDic;
    for (NSDictionary *dict in data) {
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:dict];
        [dic setValue:dict[@"createTime"] forKey:@"create_time"];
        [dic setValue:dict[@"longitude"] forKey:@"longtitude"];
        if ([dict[@"activity"] integerValue]==0 || [dict[@"activity"] integerValue]==1) {
            [dic setValue:@"静止" forKey:@"activity"];
        }else if ([dict[@"activity"] integerValue]==4){
            [dic setValue:@"驾车" forKey:@"activity"];
        }else{
            [dic setValue:@"行程" forKey:@"activity"];
        }
        
        if (tempDic) {
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
            dateFormatter.locale = [NSLocale systemLocale];
            dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
            
            NSDate *tempDate = [dateFormatter dateFromString:[tempDic[@"create_time"] substringToIndex:19]];
            NSInteger tempSecond = [tempDate timeIntervalSince1970];
            
            NSDate *dicDate = [dateFormatter dateFromString:[dic[@"create_time"] substringToIndex:19]];
            NSInteger dicSecond = [dicDate timeIntervalSince1970];
            if ((dicSecond-tempSecond)>600) {
                NSMutableDictionary *aaDic = [NSMutableDictionary dictionary];
                [aaDic setValue:[XDXTimeTool getNowTimeTimestamp] forKey:@"id"];
                [aaDic setValue:@"0" forKey:@"unlock"];
                [aaDic setValue:@"0" forKey:@"notify_log"];
                [aaDic setValue:tempDic[@"latitude"] forKey:@"latitude"];
                [aaDic setValue:tempDic[@"longtitude"] forKey:@"longtitude"];
                [aaDic setValue:tempDic[@"create_time"] forKey:@"create_time"];
                [aaDic setValue:@"静止" forKey:@"activity"];
                [aaDic setValue:@"0" forKey:@"speed"];
                [array addObject:aaDic];
                
                NSMutableDictionary *aDic = [NSMutableDictionary dictionary];
                [aDic setValue:[XDXTimeTool getNowTimeTimestamp] forKey:@"id"];
                [aDic setValue:@"0" forKey:@"unlock"];
                [aDic setValue:@"0" forKey:@"notify_log"];
                [aDic setValue:tempDic[@"latitude"] forKey:@"latitude"];
                [aDic setValue:tempDic[@"longtitude"] forKey:@"longtitude"];
                [aDic setValue:dic[@"create_time"] forKey:@"create_time"];
                [aDic setValue:@"静止" forKey:@"activity"];
                [aDic setValue:@"0" forKey:@"speed"];
                [array addObject:aDic];
            }
        }
        tempDic = [NSMutableDictionary dictionaryWithDictionary:dic];
        [array addObject:dic];
    }
    if (array.count>0) {
        if (![array.firstObject[@"create_time"] containsString:@"00:00"]) {
            if (![array.firstObject[@"activity"] isEqualToString:@"静止"]) {
                if ([[array.firstObject[@"create_time"] substringWithRange:NSMakeRange(11, 2)] integerValue]>1) {
                    {
                        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
                        [dic setValue:[XDXTimeTool getNowTimeTimestamp] forKey:@"id"];
                        [dic setValue:@"0" forKey:@"unlock"];
                        [dic setValue:@"0" forKey:@"notify_log"];
                        [dic setValue:array.firstObject[@"latitude"] forKey:@"latitude"];
                        [dic setValue:array.firstObject[@"longtitude"] forKey:@"longtitude"];
                        [dic setValue:array.firstObject[@"create_time"] forKey:@"create_time"];
                        [dic setValue:@"静止" forKey:@"activity"];
                        [dic setValue:@"静止" forKey:@"org_activity"];
                        [dic setValue:@"0" forKey:@"speed"];
                        [array insertObject:dic atIndex:0];
                    }
                    {
                        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
                        [dic setValue:[XDXTimeTool getNowTimeTimestamp] forKey:@"id"];
                        [dic setValue:@"0" forKey:@"unlock"];
                        [dic setValue:@"0" forKey:@"notify_log"];
                        [dic setValue:array.firstObject[@"latitude"] forKey:@"latitude"];
                        [dic setValue:array.firstObject[@"longtitude"] forKey:@"longtitude"];
                        [dic setValue:[array.firstObject[@"create_time"] stringByReplacingCharactersInRange:NSMakeRange(11, 8) withString:@"00:00:00"] forKey:@"create_time"];
                        [dic setValue:@"静止" forKey:@"activity"];
                        [dic setValue:@"静止" forKey:@"org_activity"];
                        [dic setValue:@"0" forKey:@"speed"];
                        [array insertObject:dic atIndex:0];
                    }
                }else{
                    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
                    [dic setValue:[XDXTimeTool getNowTimeTimestamp] forKey:@"id"];
                    [dic setValue:@"0" forKey:@"unlock"];
                    [dic setValue:@"0" forKey:@"notify_log"];
                    [dic setValue:array.firstObject[@"latitude"] forKey:@"latitude"];
                    [dic setValue:array.firstObject[@"longtitude"] forKey:@"longtitude"];
                    [dic setValue:[array.firstObject[@"create_time"] stringByReplacingCharactersInRange:NSMakeRange(11, 8) withString:@"00:00:00"] forKey:@"create_time"];
                    [dic setValue:array.firstObject[@"speed"] forKey:@"speed"];
                    [dic setValue:@"行程" forKey:@"activity"];
                    [dic setValue:dic[@"activity"] forKey:@"org_activity"];
                    [array insertObject:dic atIndex:0];
                }
            }else{
                NSMutableDictionary *dic = [NSMutableDictionary dictionary];
                [dic setValue:[XDXTimeTool getNowTimeTimestamp] forKey:@"id"];
                [dic setValue:@"0" forKey:@"unlock"];
                [dic setValue:@"0" forKey:@"notify_log"];
                [dic setValue:array.firstObject[@"latitude"] forKey:@"latitude"];
                [dic setValue:array.firstObject[@"longtitude"] forKey:@"longtitude"];
                [dic setValue:[array.firstObject[@"create_time"] stringByReplacingCharactersInRange:NSMakeRange(11, 8) withString:@"00:00:00"] forKey:@"create_time"];
                [dic setValue:@"静止" forKey:@"activity"];
                [dic setValue:dic[@"activity"] forKey:@"org_activity"];
                [dic setValue:@"0" forKey:@"speed"];
                [array insertObject:dic atIndex:0];
            }
        }
        
        NSMutableArray *tempArray = [TrackTool segmentsFromLocationArray:array];
        tempArray = [TrackTool sortFormartArray:tempArray];
        tempArray = [TrackTool moveActivityToDriveWithArray:tempArray];
        self.activityArray = tempArray;
        if (self.activityArray.count>0) {
            NSMutableDictionary *dateDic = [NSMutableDictionary dictionary];
            [dateDic setValue:array.firstObject[@"create_time"] forKey:@"date"];
            [dateDic setValue:@(array.count) forKey:@"count"];
            [dateDic setValue:@(1) forKey:@"isShow"];
            NSMutableArray *dateArray = [NSMutableArray array];
            for (int j = 0; j < self.activityArray.count; j ++) {
                NSMutableArray *array = self.activityArray[j];
                if (array.count>1) {
                    if ([array.firstObject[@"activity"] isEqualToString:@"行程"] || [array.firstObject[@"activity"] isEqualToString:@"驾车"]) {
                        if (j>0) {
                            NSMutableDictionary *foDic = [self.activityArray[j-1] lastObject];
                            [foDic setValue:array.firstObject[@"activity"] forKey:@"activity"];
                            [array insertObject:foDic atIndex:0];
                        }
                    }
                    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                    dateFormatter.locale = [NSLocale systemLocale];
                    dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
                    NSDate *firstDate = [dateFormatter dateFromString:[array.firstObject[@"create_time"] substringToIndex:19]];
                    NSInteger firstSecond = [firstDate timeIntervalSince1970];
                    
                    NSDate *lastDate = [dateFormatter dateFromString:[array.lastObject[@"create_time"] substringToIndex:19]];
                    NSInteger lastSecond = [lastDate timeIntervalSince1970];
                    
                    firstDate = [NSDate dateWithTimeIntervalSince1970:firstSecond];
                    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
                    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                    NSString *firstStr = [formatter stringFromDate:firstDate];
                    NSString *lastStr = [formatter stringFromDate:lastDate];
                    
                    NSString *time = [NSString stringWithFormat:@"%@",[firstStr substringWithRange:NSMakeRange(11, 5)]];
                    NSString *endTime = [NSString stringWithFormat:@"%@",[lastStr substringWithRange:NSMakeRange(11, 5)]];
                    NSString *timeRun = [NSString stringWithFormat:@"%@ - %@",time,endTime];
                    NSInteger second = lastSecond-firstSecond;
                    if (second/3600.0>1) {
                        timeRun = [timeRun stringByAppendingFormat:@"（%ld小时%ld分钟）",(long)(second/3600),(long)(second%3600/60)];
                    }else{
                        timeRun = [timeRun stringByAppendingFormat:@"（%@分钟）",[NSString stringWithFormat:@"%ld",(long)(second/60)]];
                    }
                    if ([array.firstObject[@"activity"] isEqualToString:@"行程"] || [array.firstObject[@"activity"] isEqualToString:@"驾车"]) {
                        double distance = 0;
                        for (int i = 1; i < array.count; i++) {
                            distance = distance+[TrackTool distanceBetweenOrderByLatitudeA:[array[i-1][@"latitude"] doubleValue] latitudeB:[array[i][@"latitude"] doubleValue] longitudeA:[array[i-1][@"longtitude"] doubleValue] longitudeB:[array[i][@"longtitude"] doubleValue]];
                        }
                        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
                        [dic setValue:array forKey:@"array"];
                        [dic setValue:time forKey:@"time"];
                        [dic setValue:timeRun forKey:@"timeRun"];
                        if ([array.firstObject[@"activity"] isEqualToString:@"行程"]) {
                            CGFloat speed = 0;
                            for (NSDictionary *dict in array) {
                                if (speed<=[dict[@"speed"] floatValue]) {
                                    speed = [dict[@"speed"] floatValue];
                                }
                            }
                            [dic setValue:[NSString stringWithFormat:@"%.0f",speed] forKey:@"maxSpeed"];
                            [dic setValue:[NSString stringWithFormat:@"行程 %.1f 公里",distance] forKey:@"title"];
                        }else if ([array.firstObject[@"activity"] isEqualToString:@"驾车"]){
                            CGFloat speed = 0;
                            for (NSDictionary *dict in array) {
                                if (speed<=[dict[@"speed"] floatValue]) {
                                    speed = [dict[@"speed"] floatValue];
                                }
                            }
                            
                            //                            // 新增逻辑：只有当原始maxSpeed <= 20时，才重新计算实际速度
                            //                            if (speed <= 20) {
                            //                                CGFloat recalculatedMaxSpeed = 0;
                            //                                for (int i = 1; i < array.count; i++) {
                            //                                    NSDictionary *prevPoint = array[i-1];
                            //                                    NSMutableDictionary *currPoint = [NSMutableDictionary dictionaryWithDictionary:array[i]]; // 转换为可变字典
                            //
                            //                                    // 计算两点间距离
                            //                                    double distance = [TrackTool distanceBetweenOrderByLatitudeA:[prevPoint[@"latitude"] doubleValue]
                            //                                                                                       latitudeB:[currPoint[@"latitude"] doubleValue]
                            //                                                                                      longitudeA:[prevPoint[@"longtitude"] doubleValue]
                            //                                                                                      longitudeB:[currPoint[@"longtitude"] doubleValue]];
                            //
                            //                                    // 计算时间差（秒）
                            //                                    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                            //                                    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                            //                                    dateFormatter.locale = [NSLocale systemLocale];
                            //                                    dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
                            //
                            //                                    NSDate *prevDate = [dateFormatter dateFromString:[prevPoint[@"create_time"] substringToIndex:19]];
                            //                                    NSDate *currDate = [dateFormatter dateFromString:[currPoint[@"create_time"] substringToIndex:19]];
                            //
                            //                                    if (prevDate && currDate) {
                            //                                        NSTimeInterval timeInterval = [currDate timeIntervalSinceDate:prevDate];
                            //
                            //                                        // 避免除零错误，时间间隔至少1秒
                            //                                        if (timeInterval >= 1.0) {
                            //                                            // 计算速度 (km/h) = 距离(km) / 时间(h)
                            //                                            CGFloat calculatedSpeed = distance / (timeInterval / 3600.0);
                            //
                            //                                            // 将重新计算的速度赋值给currPoint
                            //                                            [currPoint setValue:[NSString stringWithFormat:@"%.0f", calculatedSpeed] forKey:@"speed"];
                            //
                            //                                            // 更新array中对应的数据点
                            //                                            [array replaceObjectAtIndex:i withObject:currPoint];
                            //
                            //                                            // 更新最大速度
                            //                                            if (calculatedSpeed > recalculatedMaxSpeed) {
                            //                                                recalculatedMaxSpeed = calculatedSpeed;
                            //                                            }
                            //                                        }
                            //                                    }
                            //                                }
                            //
                            //                                // 使用重新计算的最大速度
                            //                                speed = recalculatedMaxSpeed;
                            //                            }
                            
                            
                            // 当speed > 20时，保持原有逻辑，直接使用原始speed值
                            
                            [dic setValue:[NSString stringWithFormat:@"%.0f",speed] forKey:@"maxSpeed"];
                            
                            [dic setValue:[NSString stringWithFormat:@"驾车 %.1f 公里",distance] forKey:@"title"];
                        }
                        
                        [dateArray insertObject:dic atIndex:0];
                    }else{
                        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
                        [dic setValue:array forKey:@"array"];
                        [dic setValue:time forKey:@"time"];
                        [dic setValue:timeRun forKey:@"timeRun"];
                        [dateArray insertObject:dic atIndex:0];
                        if ([self matchRegionsWithStaticPoint:array.lastObject]) {
                            [dic setValue:[self matchRegionsWithStaticPoint:array.lastObject] forKey:@"region"];
                        }
                        
                        {
                            CLLocation *location = [[CLLocation alloc] initWithLatitude:[array.lastObject[@"latitude"] floatValue] longitude:[array.lastObject[@"longtitude"] floatValue]]; // 示例坐标
                            CLGeocoder *geocoder = [[CLGeocoder alloc] init];
                            [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
                                if (error) {
                                    NSMutableDictionary *param = [NSMutableDictionary dictionary];
                                    [param setValue:array.lastObject[@"latitude"] forKey:@"lat"];
                                    [param setValue:array.lastObject[@"longtitude"] forKey:@"lon"];
                                    [param setValue:@"1" forKey:@"status"];
                                    CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
                                    [manager encryptedPOST:@"/apps/data/reversecode"
                                                parameters:param
                                                   success:^(NSDictionary *responseObject) {
                                        if ([responseObject[@"code"] integerValue]==200) {
                                            [dic setValue:[NSString stringWithFormat:@"%@ 附近",responseObject[@"data"][@"street"]] forKey:@"title"];
                                            [self.memberTrackView reloadViewWithTableList:self.tableArray];
                                        }
                                    }
                                                   failure:^(NSError *aError) {
                                        
                                    }];
                                } else {
                                    if (placemarks.count > 0) {
                                        CLPlacemark *placemark = [placemarks objectAtIndex:0];
                                        [dic setValue:[NSString stringWithFormat:@"%@ 附近",placemark.name] forKey:@"title"];
                                        [self.memberTrackView reloadViewWithTableList:self.tableArray];
                                    }
                                }
                            }];
                        }
                    }
                }
                [dateDic setValue:dateArray forKey:@"array"];
            }
            if ([dateDic[@"array"] count]>0) {
                [self.tableArray addObject:dateDic];
            }
        }
    }
    
    [UIView animateWithDuration:0.3 animations:^{
        self.bgView.alpha = 0;
    }];
}

- (void)showReloadMemberTrackViewWithInfo:(NSMutableDictionary *)info
{
    if (!self.memberTrackView) {
        [self.memberListView dismiss];
        self.memberTrackView = [[MemberTrackView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, self.superView.height) Info:info GroupInfo:self.groupInfo];
        [self.superView addSubview:self.memberTrackView];
        __block HomeViewController *selfBlock = self;
        self.memberTrackView.MemberTrackMoreBlock = ^{
            if (selfBlock.netDate<([info[@"dates"] count]-1)) {
                selfBlock.netDate = selfBlock.netDate+1;
                [selfBlock getMemberInfoWithUserId:info[@"userId"] Date:info[@"dates"][selfBlock.netDate] Success:^(NSArray *data) {
                    [selfBlock readMoreDataWithData:data Info:info];
                } Error:^(NSDictionary *data) {
                    [selfBlock.memberTrackView reloadViewWithTableList:selfBlock.tableArray];
                }];
            }
        };
        self.memberTrackView.MemberTrackRefreshBlock = ^{
            NSMutableDictionary *param = [NSMutableDictionary dictionary];
            [param setValue:info[@"userId"] forKey:@"userId"];
            CryptoHTTPKit *manager = [[CryptoHTTPKit alloc] init];
            [manager encryptedPOST:@"/apps/trajectory/dates"
                        parameters:param
                           success:^(NSDictionary *responseObject) {
                if ([responseObject[@"code"] integerValue]==200 && [responseObject[@"data"] isKindOfClass:[NSArray class]] && [responseObject[@"data"] count]>0) {
                    [info setValue:responseObject[@"data"] forKey:@"dates"];
                    selfBlock.netDate = 0;
                    [selfBlock getMemberInfoWithUserId:info[@"userId"] Date:info[@"dates"][selfBlock.netDate] Success:^(NSArray *data) {
                        [selfBlock readMoreDataWithData:data Info:info];
                    } Error:^(NSDictionary *data) {
                        [selfBlock.memberTrackView reloadViewWithTableList:selfBlock.tableArray];
                    }];
                }
            }
                           failure:^(NSError *aError) {
                
            }];
        };
        self.memberTrackView.MemberTrackClickBlock = ^(NSDictionary *aInfo) {
            NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithDictionary:aInfo];
            [dictionary setValue:info[@"avatar"] forKey:@"avatar"];
            
            MemberTrackDetailViewController *vc = [[MemberTrackDetailViewController alloc] init];
            vc.info = dictionary;
            vc.modalPresentationStyle = UIModalPresentationPopover;
            [selfBlock.tabBarController presentViewController:vc animated:YES completion:nil];
        };
        
        self.memberTrackView.MemberTrackPopBlock = ^{
            for (XDXPointAnnotation *annotation in selfBlock.locations.allValues) {
                CustomAnnotationView *annView = (CustomAnnotationView *)[selfBlock.mapView viewForAnnotation:annotation];
                NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                [selfBlock loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
            }
            [selfBlock.memberListView show];
            [selfBlock.memberTrackView removeFromSuperview];
            selfBlock.memberTrackView = nil;
            selfBlock.roomView.hidden = NO;
            selfBlock.mapButton.hidden = NO;
            selfBlock.vector.hidden = NO;
            selfBlock.add.hidden = NO;
            //            selfBlock.sosButton.hidden = NO;
            
            // GPT angular allocator init
            selfBlock.detailAnn = nil;
            CustomAnnotationView *annView = ((CustomAnnotationView *)[selfBlock.mapView viewForAnnotation:selfBlock.mapView.userLocation]);
            NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
            [selfBlock loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
            for (XDXPointAnnotation *annotation in selfBlock.locations.allValues) {
                CustomAnnotationView *annView = (CustomAnnotationView *)[selfBlock.mapView viewForAnnotation:annotation];
                NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                [selfBlock loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
            }
            
            [((XDXBaseTabBarViewController *)selfBlock.tabBarController) xdx_showCustomTabBar];
        };
    }
    
    [self.memberTrackView reloadViewWithTableList:self.tableArray];
    
    [self.superView bringSubviewToFront:self.memberTrackView];
    if (self.tabBarController.selectedIndex==0) {
        [((XDXBaseTabBarViewController *)self.tabBarController) xdx_hideCustomTabBar];
    }
}

// 给静止的时间段匹配围栏
- (NSDictionary *)matchRegionsWithStaticPoint:(NSDictionary *)point
{
    for (NSDictionary *region in self.memberListView.regions) {
        if ([TrackTool distanceBetweenOrderByLatitudeA:[point[@"latitude"] floatValue] latitudeB:[region[@"latitude"] floatValue] longitudeA:[point[@"longtitude"] floatValue] longitudeB:[region[@"longitude"] floatValue]]<=[region[@"radius"] integerValue]/1000.0) {
            return region;
        }
    }
    return nil;
}

#pragma mark - 在地图中添加家庭成员的定位标记
- (void)addAnnotationWithInfo:(NSDictionary *)info
{
    CLLocationCoordinate2D coord = CLLocationCoordinate2DMake([info[@"latitude"] doubleValue],[info[@"longtitude"] doubleValue]);
    XDXPointAnnotation *annotation = [[XDXPointAnnotation alloc] init];
    annotation.coordinate = coord;
    annotation.userId = [NSString stringWithFormat:@"%@",info[@"userId"]];
    annotation.nickName    = info[@"nickName"];
    annotation.avatar = info[@"avatar"];
    annotation.speed = @"0";
    annotation.anns = [NSMutableArray array];
    if ([info[@"battery"] isKindOfClass:[NSNull class]] || !info[@"battery"]) {
        annotation.battery = [NSString stringWithFormat:@"%ld",50+random()%20];
    }else{
        annotation.battery = [NSString stringWithFormat:@"%@",info[@"battery"]];
    }
    if ([info[@"activity"] isKindOfClass:[NSNull class]] || !info[@"activity"]) {
        annotation.activity = @"静止";
    }else{
        annotation.activity = info[@"activity"];
    }
    annotation.isCharge = NO;
    [self.mapView addAnnotation:annotation];
    [self.locations setObject:annotation forKey:[NSString stringWithFormat:@"%@",info[@"userId"]]];
    
    
}

#pragma mark - 更新家庭成员在地图中定位的UI
- (void)loadCustomAnnotionViewWithDic:(NSDictionary *)dic
                         AnnotionView:(CustomAnnotationView *)annotationView
{
    
    [annotationView.portraitImageView sd_setImageWithURL:[NSURL URLWithString:dic[@"avatar"]]];
    annotationView.batteyImg.image = [UIImage imageNamed:[dic[@"isCharge"] boolValue]?@"charge":@"battery"];
    [annotationView.batteyView setFrame:CGRectMake(annotationView.batteyImg.x+3, annotationView.batteyImg.y+8, 13*([dic[@"battery"] floatValue]/100), 5)];
    annotationView.battey.text = [NSString stringWithFormat:@"%@%%",dic[@"battery"]];
    if ([annotationView.annotation isKindOfClass:[XDXPointAnnotation class]]){
        annotationView.alpha = ((XDXPointAnnotation *)annotationView.annotation).isHide ? 0.0 : 1.0;
        if (((XDXPointAnnotation *)annotationView.annotation).anns.count>0) {
            [self cluAnnotaionWithAnnotationView:annotationView Point:((XDXPointAnnotation *)annotationView.annotation)];
        }else{
            annotationView.view.hidden = NO;
            annotationView.portraitImageView.hidden = NO;
            annotationView.groupView.hidden = YES;
            annotationView.circle.hidden = NO;
        }
    }else{
        annotationView.view.hidden = NO;
        annotationView.portraitImageView.hidden = NO;
        annotationView.groupView.hidden = YES;
        BOOL isHideUser = NO;
        for (XDXPointAnnotation *annotation in self.locations.allValues) {
            if (annotation.anns.count>0) {
                for (XDXPointAnnotation *obj in annotation.anns) {
                    if (obj.userId.integerValue == [XDXShareInstance shareInstance].userId.integerValue) {
                        isHideUser = YES;
                        break;
                    }
                }
            }
        }
        annotationView.circle.hidden = isHideUser ? YES : NO;
        annotationView.alpha = isHideUser ? 0.0 : 1.0;
        
    }
    
    if ([annotationView.annotation isKindOfClass:[XDXPointAnnotation class]]) {
        annotationView.heading.hidden = YES;
        annotationView.locationCircle.hidden = YES;
    }else{
        if (self.detailAnn==annotationView.annotation) {
            annotationView.heading.hidden = NO;
            annotationView.locationCircle.hidden = NO;
        }else{
            annotationView.heading.hidden = YES;
            annotationView.locationCircle.hidden = YES;
        }
    }
    
    annotationView.selView.hidden = (self.detailAnn==annotationView.annotation)?NO:YES;
    
    if ([dic[@"activity"] isEqualToString:@"静止"]) {
        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, 57, 35)];
        for (int i = 0; i < self.memberListView.memberList.count; i ++) {
            NSObject *obj = self.memberListView.memberList[i];
            if ([obj isKindOfClass:[NSMutableDictionary class]] && [((NSDictionary *)obj)[@"nickName"] isEqualToString:dic[@"nickName"]]){
                annotationView.activityImg.image = [UIImage imageNamed:@"dingwei-2"];
                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                dateFormatter.locale = [NSLocale systemLocale];
                dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
                NSDate *firstDate = [dateFormatter dateFromString:[[((NSDictionary *)obj)[@"timestamp"] substringToIndex:19] stringByReplacingOccurrencesOfString:@"T" withString:@" "]];
                if (firstDate) {
                    NSInteger firstSecond = [firstDate timeIntervalSince1970];
                    NSInteger lastSecond = [[XDXTimeTool getNowTimeTimestamp] integerValue];
                    NSInteger second = lastSecond-firstSecond;
                    
                    NSString *string = [NSString stringWithFormat:@"%ld小时\n%ld分钟",(long)(second/3600),(long)(second%3600/60)];
                    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:string];
                    [str addAttribute:NSForegroundColorAttributeName value:GraryLightColor range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                    [str addAttribute:NSFontAttributeName value:DEFAULT_FONT(11) range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                    annotationView.activity.attributedText = str;
                    annotationView.activity.numberOfLines = 2;
                    [annotationView.activity sizeToFit];
                    [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, annotationView.activity.width, 35)];
                    if (self.foucusAnn==annotationView.annotation) {
                        [self fullAnnotationView:annotationView];
                    }else {
                        [self hideAnnotationView:annotationView];
                    }
                }
                annotationView.battey.adjustsFontSizeToFitWidth = YES;
                annotationView.borderColor = DeepMainCoolor;
                
                break;
            }
        }
    }else if ([dic[@"activity"] isEqualToString:@"步行"] || [dic[@"activity"] isEqualToString:@"骑行"]){
        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, 57, 35)];
        for (int i = 0; i < self.memberListView.memberList.count; i ++) {
            NSObject *obj = self.memberListView.memberList[i];
            if ([obj isKindOfClass:[NSMutableDictionary class]] && [((NSDictionary *)obj)[@"nickName"] isEqualToString:dic[@"nickName"]]){
                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                dateFormatter.locale = [NSLocale systemLocale];
                dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
                NSDate *firstDate = [dateFormatter dateFromString:[[((NSDictionary *)obj)[@"timestamp"] substringToIndex:19] stringByReplacingOccurrencesOfString:@"T" withString:@" "]];
                if (firstDate) {
                    NSInteger firstSecond = [firstDate timeIntervalSince1970];
                    NSInteger lastSecond = [[XDXTimeTool getNowTimeTimestamp] integerValue];
                    NSInteger second = lastSecond-firstSecond;
                    // 最后一次运动状态超过90s，则视为静止
                    if (second>ABNORMAL_DURATION) {
                        annotationView.activityImg.image = [UIImage imageNamed:@"dingwei-2"];
                        NSString *string = [NSString stringWithFormat:@"%ld小时\n%ld分钟",(long)(second/3600),(long)(second%3600/60)];
                        NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:string];
                        [str addAttribute:NSForegroundColorAttributeName value:GraryLightColor range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                        [str addAttribute:NSFontAttributeName value:DEFAULT_FONT(11) range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                        annotationView.activity.attributedText = str;
                        annotationView.activity.numberOfLines = 2;
                        [annotationView.activity sizeToFit];
                        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, annotationView.activity.width, 35)];
                        if (self.foucusAnn==annotationView.annotation) {
                            [self fullAnnotationView:annotationView];
                        }else{
                            [self hideAnnotationView:annotationView];
                        }
                    }else{
                        annotationView.activityImg.image = [UIImage imageNamed:@"walk_ann"];
                        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, 57, 35)];
                        NSString *string = [NSString stringWithFormat:@"%@ km/h",dic[@"speed"]];
                        NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:string];
                        [str addAttribute:NSForegroundColorAttributeName value:GraryLightColor range:NSMakeRange(string.length-4, 4)];
                        [str addAttribute:NSFontAttributeName value:DEFAULT_FONT(11) range:NSMakeRange(string.length-4, 4)];
                        annotationView.activity.attributedText = str;
                        annotationView.activity.numberOfLines = 1;
                        [annotationView.activity sizeToFit];
                        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, annotationView.activity.width, 35)];
                        if (self.foucusAnn==annotationView.annotation) {
                            [self fullAnnotationView:annotationView];
                        }else{
                            [self smallAnnotationView:annotationView];
                        }
                    }
                    annotationView.battey.adjustsFontSizeToFitWidth = YES;
                    annotationView.borderColor = DeepMainCoolor;
                }
                
                break;
            }
        }
    }else if ([dic[@"activity"] isEqualToString:@"驾车"]){
        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, 57, 35)];
        for (int i = 0; i < self.memberListView.memberList.count; i ++) {
            NSObject *obj = self.memberListView.memberList[i];
            if ([obj isKindOfClass:[NSMutableDictionary class]] && [((NSDictionary *)obj)[@"nickName"] isEqualToString:dic[@"nickName"]]){
                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                dateFormatter.locale = [NSLocale systemLocale];
                dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
                NSDate *firstDate = [dateFormatter dateFromString:[[((NSDictionary *)obj)[@"timestamp"] substringToIndex:19] stringByReplacingOccurrencesOfString:@"T" withString:@" "]];
                if (firstDate) {
                    NSInteger firstSecond = [firstDate timeIntervalSince1970];
                    NSInteger lastSecond = [[XDXTimeTool getNowTimeTimestamp] integerValue];
                    NSInteger second = lastSecond-firstSecond;
                    // 最后一次运动状态超过90s，则视为静止
                    if (second>ABNORMAL_DURATION) {
                        annotationView.activityImg.image = [UIImage imageNamed:@"dingwei-2"];
                        
                        NSString *string = [NSString stringWithFormat:@"%ld小时\n%ld分钟",(long)(second/3600),(long)(second%3600/60)];
                        NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:string];
                        [str addAttribute:NSForegroundColorAttributeName value:GraryLightColor range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                        [str addAttribute:NSFontAttributeName value:DEFAULT_FONT(11) range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                        annotationView.activity.attributedText = str;
                        annotationView.activity.numberOfLines = 2;
                        [annotationView.activity sizeToFit];
                        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, annotationView.activity.width, 35)];
                        if (self.foucusAnn==annotationView.annotation) {
                            [self fullAnnotationView:annotationView];
                        }else{
                            [self hideAnnotationView:annotationView];
                        }
                    }else{
                        annotationView.activityImg.image = [UIImage imageNamed:@"drive_ann"];
                        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, 57, 35)];
                        NSString *string = [NSString stringWithFormat:@"%@ km/h",dic[@"speed"]];
                        NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:string];
                        [str addAttribute:NSForegroundColorAttributeName value:GraryLightColor range:NSMakeRange(string.length-4, 4)];
                        [str addAttribute:NSFontAttributeName value:DEFAULT_FONT(11) range:NSMakeRange(string.length-4, 4)];
                        annotationView.activity.attributedText = str;
                        annotationView.activity.numberOfLines = 1;
                        [annotationView.activity sizeToFit];
                        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, annotationView.activity.width, 35)];
                        if (self.foucusAnn==annotationView.annotation) {
                            [self fullAnnotationView:annotationView];
                        }else{
                            [self smallAnnotationView:annotationView];
                        }
                    }
                    annotationView.battey.adjustsFontSizeToFitWidth = YES;
                    annotationView.borderColor = DeepMainCoolor;
                }
                
                break;
            }
        }
    }else if ([dic[@"activity"] isEqualToString:@"sos"]){
        [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, 57, 35)];
        annotationView.activityImg.image = [UIImage imageNamed:@"icon_sos"];
        for (int i = 0; i < self.memberListView.memberList.count; i ++) {
            NSObject *obj = self.memberListView.memberList[i];
            if ([obj isKindOfClass:[NSMutableDictionary class]] && [((NSDictionary *)obj)[@"nickName"] isEqualToString:dic[@"nickName"]]){
                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
                dateFormatter.locale = [NSLocale systemLocale];
                dateFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
                NSDate *firstDate = [dateFormatter dateFromString:[[((NSDictionary *)obj)[@"timestamp"] substringToIndex:19] stringByReplacingOccurrencesOfString:@"T" withString:@" "]];
                if (firstDate) {
                    NSInteger firstSecond = [firstDate timeIntervalSince1970];
                    NSInteger lastSecond = [[XDXTimeTool getNowTimeTimestamp] integerValue];
                    NSInteger second = lastSecond-firstSecond;
                    
                    NSString *string = [NSString stringWithFormat:@"%ld小时\n%ld分钟",(long)(second/3600),(long)(second%3600/60)];
                    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:string];
                    [str addAttribute:NSForegroundColorAttributeName value:GraryLightColor range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                    [str addAttribute:NSFontAttributeName value:DEFAULT_FONT(11) range:NSMakeRange([string rangeOfString:@"时"].location+2, string.length-([string rangeOfString:@"时"].location+2))];
                    annotationView.activity.attributedText = str;
                    annotationView.activity.numberOfLines = 2;
                    [annotationView.activity sizeToFit];
                    [annotationView.activity setFrame:CGRectMake(annotationView.activityImg.maxX+5, 0, annotationView.activity.width, 35)];
                    if (self.foucusAnn==annotationView.annotation) {
                        [self fullAnnotationView:annotationView];
                    }else{
                        [self smallAnnotationView:annotationView];
                    }
                }
                annotationView.battey.adjustsFontSizeToFitWidth = YES;
                annotationView.borderColor = SOSColor;
                
            }
        }
    }
}

// 完全看不见annotationView
- (void)hideAnnotationView:(CustomAnnotationView *)annotationView
{
    [UIView animateWithDuration:0.3 animations:^{
        annotationView.activityView.transform = CGAffineTransformMakeScale(1.0/(annotationView.activity.width+37), 1.0/35);
    }];
}

// 只看的见运动图标的小annotationView
- (void)smallAnnotationView:(CustomAnnotationView *)annotationView
{
    if (annotationView.activityView.alpha != 1 || annotationView.activityView.width>30) {
        [UIView animateWithDuration:0.3 animations:^{
            [annotationView.activityView setFrame:CGRectMake(annotationView.selView.maxX-54+(annotationView.groupView.hidden==NO?(kGroupWidth-kPortraitWidth)/2:0), annotationView.selView.y+21-((annotationView.groupView.hidden==NO && ((XDXPointAnnotation *)annotationView.annotation).anns.count>2)?(kGroupWidth-kPortraitWidth):0), 30, 26)];
            annotationView.activityLayer.frame = annotationView.activityView.bounds;
            annotationView.activityLayer.cornerRadius = annotationView.activityView.height/2;
            [annotationView.activityImg setFrame:CGRectMake(6, (annotationView.activityView.height-18)/2, 18, 18)];
            annotationView.activity.alpha = 0;
        }];
    }
}

// 看的见完全状态的annotationView
- (void)fullAnnotationView:(CustomAnnotationView *)annotationView
{
    if (annotationView.activityView.width<37) {
        annotationView.activityView.layer.anchorPoint = CGPointMake(0, 0.5);
        
        annotationView.activityView.transform = CGAffineTransformMakeScale(0.85f, 0.85f);
        [UIView animateWithDuration:0.45f delay:0 usingSpringWithDamping:0.4f initialSpringVelocity:0.9f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            annotationView.activityView.transform = CGAffineTransformIdentity;
            [annotationView.activityView setFrame:CGRectMake(annotationView.selView.maxX-54+(annotationView.groupView.hidden==NO?(kGroupWidth-kPortraitWidth)/2:0), annotationView.selView.y+17-((annotationView.groupView.hidden==NO && ((XDXPointAnnotation *)annotationView.annotation).anns.count>2)?(kGroupWidth-kPortraitWidth):0), annotationView.activity.maxX+16, 35)];
            annotationView.activityLayer.frame = annotationView.activityView.bounds;
            annotationView.activityLayer.cornerRadius = annotationView.activityView.height/2;
            [annotationView.activityImg setFrame:CGRectMake(8, (annotationView.activityView.height-18)/2, 18, 18)];
            [annotationView.activity setFrame:CGRectMake(CGRectGetMaxX(annotationView.activityImg.frame)+3, 0, annotationView.activity.width, annotationView.activityView.height)];
            annotationView.activity.alpha = 1;
        } completion:nil];
    }
}

#pragma mark - mapview delegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    static NSString *userReuseId = @"UserLocationReuseId";
    static NSString *memberReuseId = @"MemberReuseId";
    
    CustomAnnotationView *annotationView = nil;
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        annotationView = (CustomAnnotationView* )[mapView dequeueReusableAnnotationViewWithIdentifier:userReuseId];
        if (annotationView == nil)
        {
            annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:userReuseId];
            annotationView.canShowCallout = NO;
            annotationView.draggable = NO;
        } else {
            annotationView.annotation = annotation;
        }
        annotationView.view.layer.anchorPoint = CGPointMake(0.5f, 0.5f);
    } else {
        annotationView = (CustomAnnotationView* )[mapView dequeueReusableAnnotationViewWithIdentifier:memberReuseId];
        if (annotationView == nil)
        {
            annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:memberReuseId];
            annotationView.canShowCallout = NO;
            annotationView.draggable = NO;
        } else {
            annotationView.annotation = annotation;
        }
    }
    
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
        [self loadCustomAnnotionViewWithDic:dict AnnotionView:annotationView];
    }else{
        [self loadCustomAnnotionViewWithDic:@{@"activity":((XDXPointAnnotation *)annotation).activity,@"battery":((XDXPointAnnotation *)annotation).battery,@"speed":((XDXPointAnnotation *)annotation).speed,@"nickName":((XDXPointAnnotation *)annotation).nickName,@"avatar":((XDXPointAnnotation *)annotation).avatar,@"isCharge":@(((XDXPointAnnotation *)annotation).isCharge)} AnnotionView:annotationView];
    }
    
    
    __block CustomAnnotationView *annotationViewBlock = annotationView;
    annotationView.CustomAnnotationClickBlock = ^{
        
        NSMutableDictionary *info;
        
        if (annotationView.annotation == self.mapView.userLocation) {
            for (NSObject *obj in self.memberListView.memberList) {
                if ([obj isKindOfClass:[NSDictionary class]] && [((NSDictionary *)obj)[@"userId"] integerValue]==[XDXShareInstance shareInstance].userId.integerValue) {
                    info = [NSMutableDictionary dictionaryWithDictionary:((NSDictionary *)obj)];
                    break;
                }
            }
        }else{
            for (NSString *key in self.locations.allKeys) {
                if (((XDXPointAnnotation *)self.locations[key]).nickName == ((XDXPointAnnotation *)annotationViewBlock.annotation).nickName && ((XDXPointAnnotation *)self.locations[key]).avatar == ((XDXPointAnnotation *)annotationViewBlock.annotation).avatar) {
                    for (NSObject *obj in self.memberListView.memberList) {
                        if ([obj isKindOfClass:[NSDictionary class]] && [((NSDictionary *)obj)[@"userId"] integerValue]==key.integerValue) {
                            info = [NSMutableDictionary dictionaryWithDictionary:((NSDictionary *)obj)];
                            break;
                        }
                    }
                    break;
                }
            }
        }
        
        if (info) {
            self.memberListView.MemberInfoBlock(info);
        }
    };
    return annotationView;
}

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views
{
    for (CustomAnnotationView *annotationView in views) {
        [annotationView.view setFrame:CGRectMake((kWidth-kPortraitWidth)/2, 0, 0, 0)];
        annotationView.viewLayer.frame = annotationView.view.bounds;
        [annotationView.portraitImageView.layer setBorderColor:RealWhiteColor.CGColor];
        annotationView.portraitImageView.layer.cornerRadius = 0;
        [annotationView.portraitImageView setFrame:CGRectMake(kWidth/2, kPortraitHeight, 0, 0)];
        
        [annotationView xdx_resetCorToDefault];
        [UIView animateWithDuration:0.3 animations:^{
            [annotationView.view setFrame:CGRectMake((kWidth-kPortraitWidth)/2, kHeight-kPortraitHeight, kPortraitHeight, kPortraitHeight+7)];
            annotationView.portraitImageView.layer.cornerRadius = 26;
            [annotationView.portraitImageView setFrame:CGRectMake(kHoriMargin, kVertMargin, annotationView.view.width-2*kHoriMargin, annotationView.view.width-2*kHoriMargin)];
        } completion:^(BOOL finished) {
            annotationView.viewLayer.frame = annotationView.view.bounds;
            [annotationView.portraitImageView.layer setBorderColor:[UIColor clearColor].CGColor];
        }];
    }
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self resolveAnnotationOverlaps];
    });
}

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay
{
    MKPolylineRenderer * polylineRenderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
    polylineRenderer.lineWidth = 5.f;
    polylineRenderer.strokeColor = GraryTooHeavyColor;
    return polylineRenderer;
}

- (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered
{
    BOOL showTraffic = [[[NSUserDefaults standardUserDefaults] objectForKey:ShowTraffic] boolValue];
    NSInteger roadNet = [[[NSUserDefaults standardUserDefaults] objectForKey:RoadNet] boolValue];
    if ([[[NSUserDefaults standardUserDefaults] objectForKey:MapType] integerValue]==2) {
        if (self.mapView.zoomLevel>16.0) {
            self.mapView.mapType = (showTraffic==0)?(roadNet==0?MKMapTypeSatellite:MKMapTypeHybrid):MKMapTypeHybridFlyover;
        }else{
            self.mapView.mapType = MKMapTypeStandard;
        }
    }
}


- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    [self resolveAnnotationOverlaps];
}


- (void)mapViewDidChangeVisibleRegion:(MKMapView *)mapView
{
    CLLocationCoordinate2D loc = [self.mapView convertPoint:CGPointMake(0, 0) toCoordinateFromView:self.mapView];
    
    double distance = [TrackTool distanceBetweenOrderByLatitudeA:loc.latitude latitudeB:self.mapView.centerCoordinate.latitude longitudeA:loc.longitude longitudeB:self.mapView.centerCoordinate.longitude];
    CustomAnnotationView *annotationView = (CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation];
    double scale = 1.52/distance;
    [annotationView.locationCircle setBounds:CGRectMake(0, 0, 100*scale, 100*scale)];
    [annotationView.locationCircle.layer setCornerRadius:annotationView.locationCircle.bounds.size.width/2];
    
    // 地图中心点离哪个人近，且这个人在屏幕之中，哪个人就是焦点
    NSObject<MKAnnotation> *ann = nil;
    BOOL noAnnotationVisible = YES;
    
    for (XDXPointAnnotation *annotation in self.locations.allValues) {
        CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
        CGRect rect = [annView convertRect:annView.portraitImageView.frame toView:self.mapView];
        if (CGRectContainsRect(self.mapView.bounds, rect) && annotation.isAnimate==NO && annView) {
            if ([TrackTool distanceBetweenOrderByLatitudeA:annotation.coordinate.latitude latitudeB:self.mapView.centerCoordinate.latitude longitudeA:annotation.coordinate.longitude longitudeB:self.mapView.centerCoordinate.longitude]<[TrackTool distanceBetweenOrderByLatitudeA:ann.coordinate.latitude latitudeB:self.mapView.centerCoordinate.latitude longitudeA:ann.coordinate.longitude longitudeB:self.mapView.centerCoordinate.longitude] && ((XDXPointAnnotation *)annotation).isHide == NO) {
                ann = annotation;
            }
            noAnnotationVisible = NO;
            annotation.isAnimate = NO;
            [((UIView *)self.superView.unVisibleLocations[annotation.userId][@"view"]) removeFromSuperview];
            annView.hidden = NO;
            NSMutableDictionary *removedInfo = self.superView.unVisibleLocations[annotation.userId];
            [self.superView.unVisibleLocations removeObjectForKey:[NSString stringWithFormat:@"%@",annotation.userId]];
            if (removedInfo) {
                BOOL wasLeft = ([removedInfo[@"x"] integerValue] == 0);
                [self markSlotsNeedResortForSide:wasLeft];
            }
        }
    }
    
    CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation];
    CGRect rect = [annView convertRect:annView.portraitImageView.frame toView:self.mapView];
    
    if (CGRectContainsRect(self.mapView.bounds,rect) && annView) {
        noAnnotationVisible = NO;
        NSMutableDictionary *removedInfo = self.superView.unVisibleLocations[[NSString stringWithFormat:@"%@",[XDXShareInstance shareInstance].userId]];
        [((UIView *)removedInfo[@"view"]) removeFromSuperview];
        [self.mapView viewForAnnotation:self.mapView.userLocation].hidden = NO;
        [self.superView.unVisibleLocations removeObjectForKey:[NSString stringWithFormat:@"%@",[XDXShareInstance shareInstance].userId]];
        if (removedInfo) {
            BOOL wasLeft = ([removedInfo[@"x"] integerValue] == 0);
            [self markSlotsNeedResortForSide:wasLeft];
        }
    }
    // 如果地图可视区域没有坐标点，则收起个人轨迹图
    if (noAnnotationVisible && self.mapView.isDrag) {
        [_memberTrackView dismiss];
        [_memberListView bottom];
        
        self.detailAnn = nil;
        CustomAnnotationView *annView = ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]);
        NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
        [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
        for (XDXPointAnnotation *annotation in self.locations.allValues) {
            CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
            NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
            [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
        }
    }
    if ([TrackTool distanceBetweenOrderByLatitudeA:self.mapView.userLocation.coordinate.latitude latitudeB:self.mapView.centerCoordinate.latitude longitudeA:self.mapView.userLocation.coordinate.longitude longitudeB:self.mapView.centerCoordinate.longitude]<[TrackTool distanceBetweenOrderByLatitudeA:ann.coordinate.latitude latitudeB:self.mapView.centerCoordinate.latitude longitudeA:ann.coordinate.longitude longitudeB:self.mapView.centerCoordinate.longitude] && ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]).alpha > 0.01) {
        ann = self.mapView.userLocation;
    }
    if (_foucusAnn != ann && self.mapView.isDrag) {
        [_memberTrackView dismiss];
        [_memberListView bottom];
        _foucusAnn = ann;
        self.detailAnn = nil;
        
        if (((CustomAnnotationView *)[self.mapView viewForAnnotation:ann]).activityView) {
            UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleSoft];
            [feedBackGenertor impactOccurred];
        }
        
        ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]).zPriority = MKAnnotationViewZPriorityMin;
        
        if ([_foucusAnn isKindOfClass:[XDXPointAnnotation class]]) {
            for (XDXPointAnnotation *annotation in self.locations.allValues) {
                CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
                annView.zPriority = MKAnnotationViewZPriorityMin;
                if (annotation.userId.integerValue != ((XDXPointAnnotation *)_foucusAnn).userId.integerValue) {
                    NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                    [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
                }
            }
            CustomAnnotationView *annView = ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]);
            NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
            [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
        }else{
            for (XDXPointAnnotation *annotation in self.locations.allValues) {
                CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
                annView.zPriority = MKAnnotationViewZPriorityMin;
                NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
            }
        }
        ((CustomAnnotationView *)[self.mapView viewForAnnotation:ann]).zPriority = MKAnnotationViewZPriorityMax;
        if (!self.mapAnnTimer) {
            self.mapAnnTimer = [NSTimer scheduledTimerWithTimeInterval:0.4 repeats:NO block:^(NSTimer * _Nonnull timer) {
                [self.mapAnnTimer invalidate];
                self.mapAnnTimer = nil;
                CustomAnnotationView *annView = ((CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation]);
                NSDictionary *dict = @{@"nickName":[XDXShareInstance shareInstance].nickName,@"avatar":[XDXShareInstance shareInstance].avatar,@"battery":[NSString stringWithFormat:@"%.0f",[UIDevice currentDevice].batteryLevel*100],@"speed":[NSString stringWithFormat:@"%d",[XDXLocationManager shareInstance].lastLocation.speed<0?0:(int)([XDXLocationManager shareInstance].lastLocation.speed*3.6)],@"activity":[XDXLocationManager shareInstance].activityString,@"isCharge":([UIDevice currentDevice].batteryState==UIDeviceBatteryStateCharging)?@"1":@"0"};
                [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
                for (XDXPointAnnotation *annotation in self.locations.allValues) {
                    CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
                    NSDictionary *dict = @{@"nickName":annotation.nickName,@"avatar":annotation.avatar,@"battery":annotation.battery,@"speed":annotation.speed,@"activity":annotation.activity,@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
                    [self loadCustomAnnotionViewWithDic:dict AnnotionView:annView];
                }
            }];
        }
    }
    
    if (self.mapView.isDrag && self.vector.alpha == 0) {
        [UIView animateWithDuration:0.3 animations:^{
            self.vector.alpha = 1;
        }];
    }
    
    [self dealAnnotation];
    
    [self.mapOperationTimer invalidate];
    self.mapOperationTimer = nil;
    if ([NotifyToast shareNotifyToast].y<STATUSHEIGHT && self.mapView.isDrag) {
        [[NotifyToast shareNotifyToast] show];
    }
    self.mapOperationTimer = [NSTimer scheduledTimerWithTimeInterval:0.4 repeats:NO block:^(NSTimer * _Nonnull timer) {
        if ([NotifyToast shareNotifyToast].y==STATUSHEIGHT) {
            [[NotifyToast shareNotifyToast] dismiss];
        }
    }];
    
    
}

#pragma mark  防重叠：根据当前地图上的 annotation 做一次简单的“弹开”
/// 特点：
/// 1. 多轮力导向弹开，保持点与点之间的最小距离
/// 2. 每个可移动点还会主动远离自己的 originalPoint，避免自己盖住真实点
/// 3. 支持“锚点”视图：参与不重叠计算，但自身不偏移（例如 MKUserLocation）
- (void)resolveAnnotationOverlaps
{
    //    // 1. 收集参与排布的视图 + 标记哪些是锚点（不偏移）
    //    NSMutableArray<MKAnnotationView *> *views = [NSMutableArray array];
    //    NSMutableArray<NSNumber *> *fixedFlags    = [NSMutableArray array]; // YES 表示锚点，不动
    //
    //    for (id<MKAnnotation> ann in self.mapView.annotations) {
    //        BOOL isFixed = NO;
    //
    //        // detailAnn 如果是某个 XDXPointAnnotation，则它是锚点；否则系统定位点是锚点
    //        if ([self.detailAnn isKindOfClass:[XDXPointAnnotation class]]) {
    //            if ([ann isKindOfClass:[XDXPointAnnotation class]] &&
    //                ((XDXPointAnnotation *)ann).userId.integerValue == ((XDXPointAnnotation *)self.detailAnn).userId.integerValue) {
    //                isFixed = YES;
    //            }
    //        }
    ////        else {
    ////            if ([ann isKindOfClass:[MKUserLocation class]]) {
    ////                isFixed = YES;
    ////            }
    ////        }
    ////
    //        CustomAnnotationView *v = (CustomAnnotationView *)[self.mapView viewForAnnotation:ann];
    //        if (v.groupView.hidden == NO) {
    //            // 分组视图也视为锚点
    //            isFixed = YES;
    //        }
    //        if (!v || v.alpha == 0.0) {
    //            continue;
    //        }
    //
    //        // 如果需要，每次从“真实位置”开始算，可以在这里归零 transform
    //        // v.transform = CGAffineTransformIdentity;
    //
    //        [views addObject:v];
    //        [fixedFlags addObject:@(isFixed)];
    //    }
    //
    //    NSUInteger count = views.count;
    //    if (count < 2) return;
    //
    //    // 2. 原始屏幕坐标
    //    NSMutableArray<NSValue *> *originalPoints = [NSMutableArray arrayWithCapacity:count];
    //    for (MKAnnotationView *v in views) {
    //        CGPoint p = [self.mapView convertCoordinate:v.annotation.coordinate
    //                                      toPointToView:self.mapView];
    //        [originalPoints addObject:[NSValue valueWithCGPoint:p]];
    //    }
    //
    //    // 3. 偏移数组（累积 dx、dy）
    //    NSMutableArray<NSValue *> *offsets = [NSMutableArray arrayWithCapacity:count];
    //    for (NSUInteger i = 0; i < count; i++) {
    //        [offsets addObject:[NSValue valueWithCGPoint:CGPointZero]];
    //    }
    //
    //    // 3.1 每个点本轮是否参与过重叠处理（用于 cor、自排斥）
    //    NSMutableArray<NSNumber *> *overlappedFlags = [NSMutableArray arrayWithCapacity:count];
    //    for (NSUInteger i = 0; i < count; i++) {
    //        [overlappedFlags addObject:@(NO)];
    //    }
    //
    //    // 参数：最大允许偏移、迭代次数、小步自排斥步长
    //    CGFloat maxOffset     = 3.0 * kWidth;
    //    NSInteger iterations  = 10;      // 弹开 + 自排斥的迭代轮数
    //    CGFloat selfStep      = 1.0f;   // 自排斥每步推开的像素
    //
    //    // 4. 多轮“矩形相交 + 小步自排斥”迭代
    //    for (NSInteger iter = 0; iter < iterations; iter++) {
    //
    //        // 4.1 基于 CustomAnnotationView.view/groupView 矩形重叠的轻量弹开
    //        for (NSUInteger i = 0; i < count; i++) {
    //            for (NSUInteger j = i + 1; j < count; j++) {
    //
    //                CGPoint pi0 = [originalPoints[i] CGPointValue];
    //                CGPoint pj0 = [originalPoints[j] CGPointValue];
    //
    //                CGPoint oi = [offsets[i] CGPointValue];
    //                CGPoint oj = [offsets[j] CGPointValue];
    //
    //                // 当前考虑偏移后的中心点坐标（mapView 坐标系）
    //                CGPoint ci = CGPointMake(pi0.x + oi.x, pi0.y + oi.y);
    //                CGPoint cj = CGPointMake(pj0.x + oj.x, pj0.y + oj.y);
    //
    //                // 取两个点当前使用的“显示矩形尺寸”（用 view 或 groupView）
    //                CustomAnnotationView *vi = (CustomAnnotationView *)views[i];
    //                CustomAnnotationView *vj = (CustomAnnotationView *)views[j];
    //
    //                CGFloat wi = 0.f, hi = 0.f;
    //                if ([vi isKindOfClass:[CustomAnnotationView class]]) {
    //                    if (!vi.view.hidden) {
    //                        wi = vi.view.bounds.size.width;
    //                        hi = vi.view.bounds.size.height;
    //                    } else {
    //                        wi = vi.groupView.bounds.size.width;
    //                        hi = vi.groupView.bounds.size.height;
    //                    }
    //                } else {
    //                    wi = vi.bounds.size.width;
    //                    hi = vi.bounds.size.height;
    //                }
    //
    //                CGFloat wj = 0.f, hj = 0.f;
    //                if ([vj isKindOfClass:[CustomAnnotationView class]]) {
    //                    if (!vj.view.hidden) {
    //                        wj = vj.view.bounds.size.width;
    //                        hj = vj.view.bounds.size.height;
    //                    } else {
    //                        wj = vj.groupView.bounds.size.width;
    //                        hj = vj.groupView.bounds.size.height;
    //                    }
    //                } else {
    //                    wj = vj.bounds.size.width;
    //                    hj = vj.bounds.size.height;
    //                }
    //
    //                if (wi <= 0.f || hi <= 0.f || wj <= 0.f || hj <= 0.f) {
    //                    continue; // 尺寸异常，直接跳过
    //                }
    //
    //                // 以中心点 + 宽高构造当前矩形（屏幕坐标下）
    //                CGRect rectI = CGRectMake(ci.x - wi * 0.5f,
    //                                          ci.y - hi * 0.5f,
    //                                          wi, hi);
    //                CGRect rectJ = CGRectMake(cj.x - wj * 0.5f,
    //                                          cj.y - hj * 0.5f,
    //                                          wj, hj);
    //
    //                // 如果矩形不相交，就不需要弹开
    //                if (!CGRectIntersectsRect(rectI, rectJ)) {
    //                    continue;
    //                }
    //
    //                // 计算真实的重叠区域
    //                CGRect inter = CGRectIntersection(rectI, rectJ);
    //                CGFloat overlapX = CGRectGetWidth(inter);
    //                CGFloat overlapY = CGRectGetHeight(inter);
    //                if (overlapX <= 0.f || overlapY <= 0.f) {
    //                    continue; // 数值误差导致的“边界贴边”，可忽略
    //                }
    //
    //                BOOL fixedI = [fixedFlags[i] boolValue];
    //                BOOL fixedJ = [fixedFlags[j] boolValue];
    //                if (fixedI && fixedJ) {
    //                    // 两个都是锚点，谁都不动
    //                    continue;
    //                }
    //
    //                // 只弹开“刚好消除重叠 + 很小的间隙”
    //                CGFloat extraMargin = 1.0f; // 很小的间隙
    //
    //                // 根据哪一方向重叠更小，选择沿 X 轴还是 Y 轴弹开（位移尽量小）
    //                if (overlapX <= overlapY) {
    //                    // 沿 X 方向弹开
    //                    CGFloat push = overlapX * 0.5f + extraMargin;
    //
    //                    // 判断左右方向：谁在左、谁在右
    //                    CGFloat dir = (CGRectGetMidX(rectI) < CGRectGetMidX(rectJ)) ? -1.0f : 1.0f;
    //                    // dir = -1 表示 i 在左 j 在右；dir = 1 表示 i 在右 j 在左
    //
    //                    if (fixedI && !fixedJ) {
    //                        // 只动 j：全部位移给 j
    //                        oj.x += (-dir) * (2.0f * push);
    //                        overlappedFlags[j] = @(YES);
    //                    } else if (!fixedI && fixedJ) {
    //                        // 只动 i
    //                        oi.x += dir * (2.0f * push);
    //                        overlappedFlags[i] = @(YES);
    //                    } else if (!fixedI && !fixedJ) {
    //                        // 两个都可动，各自承担一半
    //                        oi.x += dir * push;
    //                        oj.x += (-dir) * push;
    //                        overlappedFlags[i] = @(YES);
    //                        overlappedFlags[j] = @(YES);
    //                    }
    //                } else {
    //                    // 沿 Y 方向弹开
    //                    CGFloat push = overlapY * 0.5f + extraMargin;
    //
    //                    // 判断上下方向：谁在上谁在下
    //                    CGFloat dir = (CGRectGetMidY(rectI) < CGRectGetMidY(rectJ)) ? -1.0f : 1.0f;
    //                    // dir = -1 表示 i 在上 j 在下
    //
    //                    if (fixedI && !fixedJ) {
    //                        // 只动 j
    //                        oj.y += (-dir) * (2.0f * push);
    //                        overlappedFlags[j] = @(YES);
    //                    } else if (!fixedI && fixedJ) {
    //                        // 只动 i
    //                        oi.y += dir * (2.0f * push);
    //                        overlappedFlags[i] = @(YES);
    //                    } else if (!fixedI && !fixedJ) {
    //                        // 两个都可动
    //                        oi.y += dir * push;
    //                        oj.y += (-dir) * push;
    //                        overlappedFlags[i] = @(YES);
    //                        overlappedFlags[j] = @(YES);
    //                    }
    //                }
    //
    //                offsets[i] = [NSValue valueWithCGPoint:oi];
    //                offsets[j] = [NSValue valueWithCGPoint:oj];
    //            }
    //        }
    //
    //        // 4.2 小步自排斥：只要这一轮参与过重叠，就沿 original -> current 再推一小段
    //        for (NSUInteger i = 0; i < count; i++) {
    //            if ([fixedFlags[i] boolValue]) continue;
    //            if (![overlappedFlags[i] boolValue]) continue;
    //
    //            CGPoint pi0 = [originalPoints[i] CGPointValue];
    //            CGPoint oi  = [offsets[i] CGPointValue];
    //            CGPoint pi  = CGPointMake(pi0.x + oi.x, pi0.y + oi.y);
    //
    //            CGFloat sdx = pi.x - pi0.x;
    //            CGFloat sdy = pi.y - pi0.y;
    //            CGFloat sd  = hypot(sdx, sdy);
    //
    //            // sd==0 时给个默认方向
    //            CGFloat ux, uy;
    //            if (sd > 1e-3f) {
    //                ux = sdx / sd;
    //                uy = sdy / sd;
    //            } else {
    //                ux = 1.0f;
    //                uy = 0.0f;
    //            }
    //
    //            oi.x += ux * selfStep;
    //            oi.y += uy * selfStep;
    //
    //            offsets[i] = [NSValue valueWithCGPoint:oi];
    //        }
    //
    //        // 如果你希望每一轮重新统计 overlappedFlags，可以在此清零再算；
    //        // 目前的写法是“历史上挤过一次就一直算挤过”，你可以视需要改成每轮重置。
    //        // for (NSUInteger i = 0; i < count; i++) overlappedFlags[i] = @(NO);
    //    }
    //
    //    // 4.x 可选：在 XY 四个轴向上做一次“均匀分布”的二次排布（偏移尽量小）
    //    // 不改变 overlappedFlags，只是对 offsets 做一个轻量的微调，以获得更均匀的视觉分布
    //    CGFloat fourAxisSpacing = kWidth + 2.0f;   // 同一轴上，相邻两个点之间的间距，可按效果再调
    //    [self xdx_balanceOffsetsOnFourAxesWithOriginalPoints:originalPoints
    //                                                 offsets:offsets
    //                                              fixedFlags:fixedFlags
    //                                             baseSpacing:fourAxisSpacing
    //                                               maxOffset:maxOffset];
    //
    //    // 5. 限制最大偏移 + 计算 newPoint + 驱动 cor（保持你现在的写法，可以继续用 overlappedFlags 控制 cor）
    //    for (NSUInteger i = 0; i < count; i++) {
    //        CGPoint o = [offsets[i] CGPointValue];
    //
    //        // 5.0 “纯 X 偏移”的全局处理：如果几乎只有 X 位移，则在 Y 方向向下偏移 kPortraitWidth/2
    //        // fabs(o.x) > 1e-3f：确保确实有明显的 X 偏移
    //        // fabs(o.y) < 1e-3f：认为 Y 方向基本为 0（纯 X）
    //        if (fabs(o.x) > 1e-3f && fabs(o.y) < 1e-3f) {
    //            o.y += kPortraitWidth * 0.5f;   // UIKit 坐标中，Y 增大是向下
    //        }
    //
    //        // 5.1 最大偏移裁剪
    //        CGFloat d = hypot(o.x, o.y);
    //        if (d > maxOffset) {
    //            CGFloat scale = maxOffset / d;
    //            o.x *= scale;
    //            o.y *= scale;
    //        }
    //
    //        CustomAnnotationView *v = (CustomAnnotationView *)views[i];
    //        CGPoint originalPoint = [originalPoints[i] CGPointValue];
    //
    //        CGPoint newPoint = CGPointMake(originalPoint.x + o.x,
    //                                       originalPoint.y + o.y);
    //
    //        if ([v isKindOfClass:[CustomAnnotationView class]]) {
    //            CustomAnnotationView *annView = (CustomAnnotationView *)v;
    //
    //            if ([overlappedFlags[i] boolValue]) {
    //                // 和别人发生过重叠：让 cor 指向 originalPoint（沿你现在的方案）
    //                CGFloat dx  = originalPoint.x - newPoint.x;
    //                CGFloat ady = originalPoint.y - newPoint.y + kPortraitWidth * 0.5f;
    //                CGFloat angle = atan2(ady, dx);
    //                CGRect corRect = CGRectMake(newPoint.x - kPortraitWidth * 0.5f,
    //                                            newPoint.y - kPortraitWidth,
    //                                            kPortraitWidth,
    //                                            kPortraitWidth);
    //                CGPoint rectCenter = CGPointMake(CGRectGetMidX(corRect),
    //                                                 CGRectGetMidY(corRect));
    //                CGFloat distance = hypot(originalPoint.x - rectCenter.x,
    //                                         originalPoint.y - rectCenter.y);
    //                [annView xdx_updateCorWithAngle:angle Point:o distance:distance];
    //            } else {
    //                // 完全没和别人挤过：cor 恢复原位
    //                [annView xdx_resetCorToDefault];
    //            }
    //        }
    //    }
    //
    //    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    //        [self dealAnnotation];
    //    });
}

#pragma mark - XY 四轴均衡分布辅助方法

/// 在 X/Y 四个方向上，尽量均匀地分布可移动点的 offset（基于 originalPoints / offsets / fixedFlags）
/// - 参数说明：
///   originalPoints: 每个 annotation 的原始屏幕坐标（你 resolveAnnotationOverlaps 里已有的）
///   offsets:        当前已经算出的偏移（本方法会修改这些值）
///   fixedFlags:     是否为锚点（锚点不参与重新分布）
///   spacing:        同一方向上，相邻两个点之间的间距（建议 >= kWidth）
///   maxOffset:      单个点允许的最大偏移半径
- (void)xdx_balanceOffsetsOnFourAxesWithOriginalPoints:(NSArray<NSValue *> *)originalPoints
                                               offsets:(NSMutableArray<NSValue *> *)offsets
                                            fixedFlags:(NSArray<NSNumber *> *)fixedFlags
                                           baseSpacing:(CGFloat)spacing
                                             maxOffset:(CGFloat)maxOffset
{
    NSUInteger count = offsets.count;
    if (count == 0 || count != originalPoints.count || count != fixedFlags.count) {
        return;
    }
    
    // 1. 计算一个几何中心（只看可移动点），作为四个轴的参考中心
    CGFloat sumX = 0.f, sumY = 0.f;
    NSInteger movableCount = 0;
    for (NSUInteger i = 0; i < count; i++) {
        if ([fixedFlags[i] boolValue]) continue;
        CGPoint p = [originalPoints[i] CGPointValue];
        sumX += p.x;
        sumY += p.y;
        movableCount++;
    }
    if (movableCount == 0) return;
    CGPoint center = CGPointMake(sumX / movableCount, sumY / movableCount);
    
    // 2. 按“离中心距离”从近到远排序，保证内圈点位移更小
    typedef struct {
        NSUInteger idx;
        CGFloat    dist;
    } XDXIdxDist;
    
    NSMutableArray<NSValue *> *sorted = [NSMutableArray array];
    for (NSUInteger i = 0; i < count; i++) {
        if ([fixedFlags[i] boolValue]) continue;
        CGPoint p = [originalPoints[i] CGPointValue];
        CGFloat d = hypot(p.x - center.x, p.y - center.y);
        XDXIdxDist s = { i, d };
        [sorted addObject:[NSValue value:&s withObjCType:@encode(XDXIdxDist)]];
    }
    [sorted sortUsingComparator:^NSComparisonResult(NSValue * _Nonnull obj1, NSValue * _Nonnull obj2) {
        XDXIdxDist a, b;
        [obj1 getValue:&a];
        [obj2 getValue:&b];
        if (a.dist < b.dist) return NSOrderedAscending;
        if (a.dist > b.dist) return NSOrderedDescending;
        return NSOrderedSame;
    }];
    
    // 3. 四个方向单位向量：右、上、左、下
    CGPoint dirs[4] = {
        {  1.0f,  0.0f }, // 右
        {  0.0f, -1.0f }, // 上
        { -1.0f,  0.0f }, // 左
        {  0.0f,  1.0f }  // 下
    };
    NSInteger dirCounts[4] = {0, 0, 0, 0};
    
    // 一条轴上大致能放几个点（超过就认为太远了）
    NSInteger maxStepsPerDir = (NSInteger)floor(maxOffset / MAX(spacing, 1.f));
    if (maxStepsPerDir <= 0) maxStepsPerDir = 1;
    
    for (NSValue *v in sorted) {
        XDXIdxDist s;
        [v getValue:&s];
        NSUInteger i = s.idx;
        
        CGPoint pi0 = [originalPoints[i] CGPointValue];
        CGPoint oi0 = [offsets[i] CGPointValue];
        CGPoint current = CGPointMake(pi0.x + oi0.x, pi0.y + oi0.y);
        
        // 为当前点选择“最合适”的方向：在四个方向中，找一个
        //   1）这条轴上的已有数量不超过 maxStepsPerDir
        //   2）targetPos 离 current 越近越好（代价最小）
        CGFloat   bestCost   = CGFLOAT_MAX;
        NSInteger bestDir    = -1;
        CGPoint   bestOffset = oi0;
        
        for (NSInteger k = 0; k < 4; k++) {
            if (dirCounts[k] >= maxStepsPerDir) {
                // 该方向已经排得太长了，跳过
                continue;
            }
            
            NSInteger stepIndex = dirCounts[k] + 1;    // 第几个点
            CGFloat   stepDist  = spacing * stepIndex; // 离原点的距离
            
            CGPoint targetOffset = CGPointMake(dirs[k].x * stepDist,
                                               dirs[k].y * stepDist);
            CGPoint targetPos = CGPointMake(pi0.x + targetOffset.x,
                                            pi0.y + targetOffset.y);
            
            CGFloat dx = targetPos.x - current.x;
            CGFloat dy = targetPos.y - current.y;
            CGFloat cost = hypot(dx, dy);
            
            if (cost < bestCost) {
                bestCost   = cost;
                bestDir    = k;
                bestOffset = targetOffset;
            }
        }
        
        if (bestDir >= 0) {
            dirCounts[bestDir] += 1;
            
            // 再裁一遍 maxOffset，防止太远
            CGFloat d = hypot(bestOffset.x, bestOffset.y);
            if (d > maxOffset) {
                CGFloat scale = maxOffset / d;
                bestOffset.x *= scale;
                bestOffset.y *= scale;
            }
            
            offsets[i] = [NSValue valueWithCGPoint:bestOffset];
        }
    }
}

#pragma mark - 在地图外的头像处理
- (void)dealAnnotation
{
    for (XDXPointAnnotation *annotation in self.locations.allValues) {
        if (!annotation.userId) {
            continue;
        }
        
        CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
        CGRect rect = [annView convertRect:annView.portraitImageView.frame toView:self.mapView];
        
        if ((!CGRectContainsRect(self.mapView.bounds, rect) && annotation.coordinate.latitude>0 && annotation.coordinate.longitude>0) || !annView) {
            CGPoint outPoint = [self.mapView convertCoordinate:annotation.coordinate toPointToView:self.mapView];
            NSInteger targetX = (outPoint.x < (SCREEN_WIDTH / 2.0f)) ? 0 : (SCREEN_WIDTH - BubbleSide);
            CGFloat preferredY = [self clampedEdgeYForValue:outPoint.y];
            BOOL isLeftSide = (targetX == 0);
            
            NSMutableDictionary *storedInfo = [self offscreenInfoForUserId:annotation.userId actualKey:nil];
            if (storedInfo) {
                storedInfo[@"preferredY"] = @(preferredY);
                storedInfo[@"y"] = @(preferredY);
                storedInfo[@"x"] = @(targetX);
                storedInfo[@"annotation"] = annotation;
                if (!storedInfo[@"slotOrder"]) {
                    storedInfo[@"slotOrder"] = @([self nextSlotSequenceForSide:isLeftSide]);
                }
                UIView *targetView = storedInfo[@"view"];
                if ([targetView isKindOfClass:[UIView class]]) {
                    targetView.x = targetX;
                }
                [self setCornerWithDic:storedInfo Layer:storedInfo[@"layer"]];
                continue;
            }
            
            if (annotation.isAnimate) {
                continue;
            }
            
            annotation.isAnimate = YES;
            UIButton *view = [[UIButton alloc] initWithFrame:rect];
            view.layer.masksToBounds = NO;
            if (self.memberTrackView) {
                [self.superView insertSubview:view belowSubview:self.memberTrackView];
            }else{
                [self.superView addSubview:view];
            }
            
            [[view rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
                for (NSMutableDictionary *dic in self.memberListView.memberList) {
                    if ([dic[@"userId"] integerValue]==annotation.userId.integerValue) {
                        if ([dic isKindOfClass:[NSDictionary class]]) {
                            self.memberListView.MemberInfoBlock(dic);
                        }
                        break;
                    }
                }
            }];
            NSMutableDictionary *dic = [NSMutableDictionary dictionary];
            dic[@"annotation"] = annotation;
            dic[@"x"] = @(targetX);
            dic[@"y"] = @(preferredY);
            dic[@"preferredY"] = @(preferredY);
            dic[@"needsEntryAnimation"] = @(YES);
            dic[@"slotOrder"] = @([self nextSlotSequenceForSide:isLeftSide]);
            [dic setValue:view forKey:@"view"];
            
            UIView *coImg = [[UIView alloc] initWithFrame:CGRectMake(0, -10, 66, 86)];
            coImg.alpha = 0;
            coImg.backgroundColor = UIColor.clearColor;
            coImg.layer.masksToBounds = NO;
            coImg.layer.shadowColor = RealBlackColor.CGColor;
            coImg.layer.shadowOffset = CGSizeMake(0,2);
            coImg.layer.shadowOpacity = 0.1;
            coImg.layer.shadowRadius = 10;
            [view addSubview:coImg];
            
            UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
            UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
            effectView.frame = coImg.bounds;
            effectView.userInteractionEnabled = NO;
            effectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
            effectView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.25];
            [coImg addSubview:effectView];
            
            CAShapeLayer *maskLayer = [CAShapeLayer layer];
            maskLayer.frame = coImg.bounds;
            effectView.layer.mask = maskLayer;
            
            [dic setValue:coImg forKey:@"coImg"];
            [dic setValue:effectView forKey:@"effectView"];
            [dic setValue:maskLayer forKey:@"layer"];
            
            [self setCornerWithDic:dic Layer:maskLayer];
            
            UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(kHoriMargin, kHoriMargin, 60, 60)];
            img.layer.masksToBounds = YES;
            [img.layer setBorderWidth:2];
            [img.layer setBorderColor:[RealWhiteColor colorWithAlphaComponent:1].CGColor];
            [img.layer setCornerRadius:26];
            [img sd_setImageWithURL:[NSURL URLWithString:annotation.avatar]];
            [view addSubview:img];
            
            [dic setValue:coImg forKey:@"img"];
            dic[@"avatarView"] = img;
            
            annView.hidden = YES;
            
            [self.superView.unVisibleLocations setValue:dic forKey:annotation.userId];
            [self markSlotsNeedResortForSide:isLeftSide];
        }
    }
    
    CustomAnnotationView *annView = (CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation];
    CGRect rect = [annView convertRect:annView.portraitImageView.frame toView:self.mapView];
    if ((!CGRectContainsRect(self.mapView.bounds, rect) && self.mapView.userLocation.coordinate.latitude>0 && self.mapView.userLocation.coordinate.longitude>0) || !annView) {
        CGPoint outPoint = [self.mapView convertCoordinate:self.mapView.userLocation.coordinate toPointToView:self.mapView];
        NSInteger targetX = (outPoint.x < (SCREEN_WIDTH / 2.0f)) ? 0 : (SCREEN_WIDTH - BubbleSide);
        CGFloat preferredY = [self clampedEdgeYForValue:outPoint.y];
        BOOL isLeftSide = (targetX == 0);
        NSString *currentUserKey = [NSString stringWithFormat:@"%@",[XDXShareInstance shareInstance].userId];
        NSMutableDictionary *storedInfo = [self offscreenInfoForUserId:[XDXShareInstance shareInstance].userId actualKey:nil];
        if (storedInfo) {
            storedInfo[@"preferredY"] = @(preferredY);
            storedInfo[@"y"] = @(preferredY);
            storedInfo[@"x"] = @(targetX);
            storedInfo[@"annotation"] = self.mapView.userLocation;
            if (!storedInfo[@"slotOrder"]) {
                storedInfo[@"slotOrder"] = @([self nextSlotSequenceForSide:isLeftSide]);
            }
            UIView *targetView = storedInfo[@"view"];
            if ([targetView isKindOfClass:[UIView class]]) {
                targetView.x = targetX;
            }
            [self setCornerWithDic:storedInfo Layer:storedInfo[@"layer"]];
        }else {
            CGPoint userPoint = [self.mapView convertCoordinate:self.mapView.userLocation.coordinate toPointToView:self.mapView];
            UIButton *view = [[UIButton alloc] initWithFrame:rect];
            view.layer.masksToBounds = NO;
            
            if (self.memberTrackView) {
                [self.superView insertSubview:view belowSubview:self.memberTrackView];
            }else{
                [self.superView addSubview:view];
            }
            
            [[view rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
                for (NSMutableDictionary *dic in self.memberListView.memberList) {
                    if ([dic[@"userId"] integerValue]==[XDXShareInstance shareInstance].userId.integerValue) {
                        if ([dic isKindOfClass:[NSDictionary class]]) {
                            self.memberListView.MemberInfoBlock(dic);
                        }
                        break;
                    }
                }
            }];
            
            NSMutableDictionary *dic = [NSMutableDictionary dictionary];
            dic[@"annotation"] = self.mapView.userLocation;
            dic[@"x"] = @(targetX);
            dic[@"y"] = @(preferredY);
            dic[@"preferredY"] = @(preferredY);
            dic[@"needsEntryAnimation"] = @(YES);
            dic[@"isCurrentUser"] = @(YES);
            dic[@"slotOrder"] = @([self nextSlotSequenceForSide:isLeftSide]);
            dic[@"view"] = view;
            
            UIView *coImg = [[UIView alloc] initWithFrame:CGRectMake(0, -10, 66, 86)];
            coImg.alpha = 0;
            coImg.backgroundColor = UIColor.clearColor;
            coImg.layer.masksToBounds = NO;
            coImg.layer.shadowColor = RealBlackColor.CGColor;
            coImg.layer.shadowOffset = CGSizeMake(0,2);
            coImg.layer.shadowOpacity = 0.1;
            coImg.layer.shadowRadius = 3;
            [view addSubview:coImg];
            
            dic[@"coImg"] = coImg;
            
            UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
            UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
            effectView.frame = coImg.bounds;
            effectView.userInteractionEnabled = NO;
            effectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
            effectView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.25];
            [coImg addSubview:effectView];
            
            CAShapeLayer *layer = [CAShapeLayer layer];
            layer.frame = coImg.bounds;
            effectView.layer.mask = layer;
            
            dic[@"effectView"] = effectView;
            dic[@"layer"] = layer;
            
            [self setCornerWithDic:dic Layer:layer];
            
            UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(kHoriMargin, kHoriMargin, 60, 60)];
            img.layer.masksToBounds = YES;
            [img.layer setBorderWidth:2];
            [img.layer setBorderColor:[RealWhiteColor colorWithAlphaComponent:1].CGColor];
            [img.layer setCornerRadius:26];
            [img sd_setImageWithURL:[NSURL URLWithString:[XDXShareInstance shareInstance].avatar]];
            [view addSubview:img];
            
            dic[@"img"] = coImg;
            dic[@"avatarView"] = img;
            
            annView.hidden = YES;
            
            [self.superView.unVisibleLocations setValue:dic forKey:currentUserKey];
            [self markSlotsNeedResortForSide:isLeftSide];
        }
    }
    
    [self layoutOffscreenButtons];
}

- (NSMutableDictionary *)offscreenInfoForUserId:(id)userId
                                      actualKey:(NSString **)actualKey
{
    if (!userId) {
        return nil;
    }
    
    id directKey = userId;
    NSMutableDictionary *directInfo = self.superView.unVisibleLocations[directKey];
    if (directInfo) {
        if (actualKey) {
            *actualKey = [directKey description];
        }
        return directInfo;
    }
    
    NSInteger identifierValue = [userId integerValue];
    for (NSString *key in self.superView.unVisibleLocations.allKeys) {
        if (key.integerValue == identifierValue) {
            if (actualKey) {
                *actualKey = key;
            }
            return self.superView.unVisibleLocations[key];
        }
    }
    
    return nil;
}

- (CGFloat)clampedEdgeYForValue:(CGFloat)value
{
    CGFloat minY = self.roomView.maxY + 5.f;
    
    CGFloat maxY = self.vector.layer.presentationLayer.frame.origin.y - 45.f;
    CGFloat minimumSpan = BubbleSide;
    if (maxY - minY < minimumSpan) {
        maxY = minY + minimumSpan;
    }
    
    if (value < minY) {
        return minY;
    }
    if (value > maxY) {
        return maxY;
    }
    return value;
}

- (NSInteger)nextSlotSequenceForSide:(BOOL)isLeft
{
    if (isLeft) {
        self.leftOffscreenSequence += 1;
        return self.leftOffscreenSequence;
    }
    self.rightOffscreenSequence += 1;
    return self.rightOffscreenSequence;
}

- (void)markSlotsNeedResortForSide:(BOOL)isLeft
{
    if (isLeft) {
        self.leftNeedsSlotResort = YES;
    } else {
        self.rightNeedsSlotResort = YES;
    }
}

- (void)layoutOffscreenButtons
{
    if (self.superView.unVisibleLocations.count == 0) {
        return;
    }
    
    CGFloat minY = self.roomView.maxY + 5.f;
    CGFloat bubbleSide = BubbleSide;
    
    CALayer *vectorLayer = self.vector.layer.presentationLayer ?: self.vector.layer;
    CALayer *memberListLayer = self.memberListView.layer.presentationLayer ?: self.memberListView.layer;
    
    CGFloat rightMaxY = vectorLayer.frame.origin.y - 45.f;
    CGFloat leftMaxY = memberListLayer.frame.origin.y - 45.f;
    
    if (rightMaxY - minY < bubbleSide) {
        rightMaxY = minY + bubbleSide;
    }
    if (leftMaxY - minY < bubbleSide) {
        leftMaxY = minY + bubbleSide;
    }
    
    [self layoutOffscreenButtonsForSide:YES minY:minY maxY:leftMaxY];
    [self layoutOffscreenButtonsForSide:NO minY:minY maxY:rightMaxY];
    
    return;
}

- (void)layoutOffscreenButtonsForSide:(BOOL)isLeftSide
                                 minY:(CGFloat)minY
                                 maxY:(CGFloat)maxY
{
    const CGFloat bubbleSide = BubbleSide;
    const CGFloat defaultSpacing = 6.f;
    
    NSMutableArray<NSMutableDictionary *> *slots = [NSMutableArray array];
    for (NSString *key in self.superView.unVisibleLocations.allKeys) {
        NSMutableDictionary *info = self.superView.unVisibleLocations[key];
        if (![info isKindOfClass:[NSMutableDictionary class]]) {
            continue;
        }
        NSNumber *xNumber = info[@"x"];
        if (!xNumber) {
            continue;
        }
        BOOL slotIsLeft = ([xNumber integerValue] == 0);
        if (slotIsLeft != isLeftSide) {
            continue;
        }
        if (![info[@"view"] isKindOfClass:[UIView class]]) {
            continue;
        }
        if (!info[@"preferredY"]) {
            info[@"preferredY"] = info[@"y"] ?: @(minY);
        }
        if (!info[@"slotOrder"]) {
            info[@"slotOrder"] = @([self nextSlotSequenceForSide:isLeftSide]);
        }
        [slots addObject:info];
    }
    
    if (slots.count == 0) {
        return;
    }
    
    BOOL needsResort = isLeftSide ? self.leftNeedsSlotResort : self.rightNeedsSlotResort;
    if (needsResort) {
        [slots sortUsingComparator:^NSComparisonResult(NSMutableDictionary *obj1, NSMutableDictionary *obj2) {
            CGFloat y1 = [obj1[@"preferredY"] floatValue];
            CGFloat y2 = [obj2[@"preferredY"] floatValue];
            if (y1 < y2) return NSOrderedAscending;
            if (y1 > y2) return NSOrderedDescending;
            return NSOrderedSame;
        }];
        
        NSInteger idx = 0;
        for (NSMutableDictionary *info in slots) {
            info[@"slotOrder"] = @(idx++);
        }
        
        if (isLeftSide) {
            self.leftNeedsSlotResort = NO;
            self.leftOffscreenSequence = idx;
        } else {
            self.rightNeedsSlotResort = NO;
            self.rightOffscreenSequence = idx;
        }
    }
    
    [slots sortUsingComparator:^NSComparisonResult(NSMutableDictionary *obj1, NSMutableDictionary *obj2) {
        NSInteger order1 = [obj1[@"slotOrder"] integerValue];
        NSInteger order2 = [obj2[@"slotOrder"] integerValue];
        if (order1 != order2) {
            return order1 < order2 ? NSOrderedAscending : NSOrderedDescending;
        }
        CGFloat y1 = [obj1[@"preferredY"] floatValue];
        CGFloat y2 = [obj2[@"preferredY"] floatValue];
        if (y1 < y2) return NSOrderedAscending;
        if (y1 > y2) return NSOrderedDescending;
        return NSOrderedSame;
    }];
    
    CGFloat availableHeight = maxY - minY;
    CGFloat requiredHeight = (bubbleSide * slots.count) + (MAX(slots.count - 1, 0) * defaultSpacing);
    CGFloat effectiveSpacing = defaultSpacing;
    if (requiredHeight > availableHeight && slots.count > 1) {
        effectiveSpacing = MAX(0.f, (availableHeight - (bubbleSide * slots.count)) / (slots.count - 1));
    }
    
    CGFloat stride = bubbleSide + effectiveSpacing;
    CGFloat maxStartY = maxY - bubbleSide;
    
    NSMutableArray<NSNumber *> *minBounds = [NSMutableArray arrayWithCapacity:slots.count];
    NSMutableArray<NSNumber *> *maxBounds = [NSMutableArray arrayWithCapacity:slots.count];
    NSMutableArray<NSNumber *> *positions = [NSMutableArray arrayWithCapacity:slots.count];
    
    for (NSUInteger idx = 0; idx < slots.count; idx++) {
        CGFloat minBound = minY + stride * idx;
        CGFloat maxBound = maxStartY - stride * (slots.count - 1 - idx);
        if (minBound > maxStartY) {
            minBound = maxStartY;
        }
        if (maxBound < minBound) {
            maxBound = minBound;
        }
        [minBounds addObject:@(minBound)];
        [maxBounds addObject:@(maxBound)];
        
        CGFloat preferred = [slots[idx][@"preferredY"] floatValue];
        CGFloat clamped = MIN(MAX(preferred, minBound), maxBound);
        [positions addObject:@(clamped)];
    }
    
    for (NSInteger iteration = 0; iteration < 4; iteration++) {
        BOOL adjusted = NO;
        
        for (NSUInteger idx = 1; idx < positions.count; idx++) {
            CGFloat previous = [positions[idx - 1] floatValue];
            CGFloat current = [positions[idx] floatValue];
            CGFloat minAllowed = MAX([minBounds[idx] floatValue], previous + stride);
            if (current < minAllowed) {
                CGFloat newValue = MIN(minAllowed, [maxBounds[idx] floatValue]);
                CGFloat delta = newValue - current;
                if (delta > 0.001f) {
                    positions[idx] = @(newValue);
                    adjusted = YES;
                }
            }
        }
        
        if (positions.count <= 1) {
            break;
        }
        
        for (NSInteger idx = (NSInteger)positions.count - 2; idx >= 0; idx--) {
            CGFloat next = [positions[idx + 1] floatValue];
            CGFloat current = [positions[idx] floatValue];
            CGFloat maxAllowed = MIN([maxBounds[idx] floatValue], next - stride);
            if (current > maxAllowed) {
                CGFloat newValue = MAX(maxAllowed, [minBounds[idx] floatValue]);
                CGFloat delta = current - newValue;
                if (delta > 0.001f) {
                    positions[idx] = @(newValue);
                    adjusted = YES;
                }
            }
        }
        
        if (!adjusted) {
            break;
        }
    }
    
    CGFloat targetX = isLeftSide ? 0.f : (SCREEN_WIDTH - bubbleSide);
    [slots enumerateObjectsUsingBlock:^(NSMutableDictionary *info, NSUInteger idx, BOOL * _Nonnull stop) {
        CGFloat targetY = [positions[idx] floatValue];
        CGRect targetFrame = CGRectMake(targetX, targetY, bubbleSide, bubbleSide);
        info[@"x"] = @(targetX);
        info[@"y"] = @(targetY);
        [self applyLayoutForInfo:info targetFrame:targetFrame];
    }];
}

- (void)applyLayoutForInfo:(NSMutableDictionary *)info
               targetFrame:(CGRect)targetFrame
{
    UIView *view = info[@"view"];
    if (![view isKindOfClass:[UIView class]]) {
        return;
    }
    
    UIView *coImg = info[@"coImg"];
    UIImageView *img = info[@"avatarView"];
    if (![img isKindOfClass:[UIImageView class]]) {
        img = info[@"img"];
    }
    CAShapeLayer *layer = info[@"layer"];
    BOOL needsEntry = [info[@"needsEntryAnimation"] boolValue];
    
    void (^applyVisualState)(void) = ^{
        view.frame = targetFrame;
        if ([coImg isKindOfClass:[UIView class]]) {
            coImg.alpha = 1.f;
            coImg.frame = CGRectMake(0, -6, 28, 40);
        }
        if ([img isKindOfClass:[UIImageView class]]) {
            img.frame = CGRectMake(2, 2, 24, 24);
            img.layer.cornerRadius = 10;
            img.layer.borderColor = [UIColor clearColor].CGColor;
        }
        if (layer && [coImg isKindOfClass:[UIView class]]) {
            layer.frame = coImg.bounds;
            [self setCornerWithDic:info Layer:layer];
        }
    };
    
    if (needsEntry) {
        if (fabs(targetFrame.origin.x-view.x)>SCREEN_WIDTH/2) {
            applyVisualState();
            info[@"needsEntryAnimation"] = @(NO);
            id annotation = info[@"annotation"];
            if ([annotation isKindOfClass:[XDXPointAnnotation class]]) {
                ((XDXPointAnnotation *)annotation).isAnimate = NO;
            }
        }else{
            [UIView animateWithDuration:0.3 animations:^{
                applyVisualState();
            } completion:^(BOOL finished) {
                info[@"needsEntryAnimation"] = @(NO);
                id annotation = info[@"annotation"];
                if ([annotation isKindOfClass:[XDXPointAnnotation class]]) {
                    ((XDXPointAnnotation *)annotation).isAnimate = NO;
                }
            }];
        }
    } else {
        applyVisualState();
    }
}

- (void)setCornerWithDic:(NSDictionary *)dic
                   Layer:(CAShapeLayer *)layer
{
    if (![layer isKindOfClass:[CAShapeLayer class]]) {
        return;
    }
    
    UIView *coImg = dic[@"coImg"];
    coImg.userInteractionEnabled = NO;
    if (![coImg isKindOfClass:[UIView class]]) {
        return;
    }
    
    BOOL isLeft = ([dic[@"x"] integerValue] == 0);
    CGRect bounds = coImg.bounds;
    UIBezierPath *path = [self bubblePathForBounds:bounds arrowOnLeft:isLeft];
    
    layer.frame = bounds;
    layer.path = path.CGPath;
    layer.fillColor = [UIColor whiteColor].CGColor;
    layer.opacity = 0.95f;
    
    coImg.layer.shadowPath = path.CGPath;
}

- (UIBezierPath *)bubblePathForBounds:(CGRect)bounds
                          arrowOnLeft:(BOOL)isLeft
{
    CGFloat arrowWidth = BubbleSide;
    CGFloat cornerRadius = 6.f;
    
    CGFloat minX = CGRectGetMinX(bounds);
    CGFloat maxX = CGRectGetMaxX(bounds);
    CGFloat minY = CGRectGetMinY(bounds);
    CGFloat maxY = CGRectGetMaxY(bounds);
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    if (isLeft) {
        [path moveToPoint:CGPointMake(minX , minY)];
        [path addQuadCurveToPoint:CGPointMake(maxX-8, minY + cornerRadius)
                     controlPoint:CGPointMake(minX+5, minY + cornerRadius)];
        
        [path addQuadCurveToPoint:CGPointMake(maxX, minY + cornerRadius+8)
                     controlPoint:CGPointMake(maxX-2, minY + cornerRadius+2)];
        
        [path addLineToPoint:CGPointMake(maxX, minY + cornerRadius + arrowWidth-8)];
        
        [path addQuadCurveToPoint:CGPointMake(maxX-8, minY + cornerRadius + arrowWidth)
                     controlPoint:CGPointMake(maxX-2, minY + cornerRadius + arrowWidth-2)];
        
        [path addQuadCurveToPoint:CGPointMake(minX, maxY)
                     controlPoint:CGPointMake(minX+5, minY + cornerRadius + arrowWidth)];
        [path addLineToPoint:CGPointMake(minX , minY)];
    }else{
        [path moveToPoint:CGPointMake(maxX , minY)];
        [path addQuadCurveToPoint:CGPointMake(minX+8, minY + cornerRadius)
                     controlPoint:CGPointMake(maxX-5, minY + cornerRadius)];
        
        [path addQuadCurveToPoint:CGPointMake(minX, minY + cornerRadius + 8)
                     controlPoint:CGPointMake(minX+2, minY + cornerRadius + 2)];
        
        [path addLineToPoint:CGPointMake(minX, minY + cornerRadius + arrowWidth - 8)];
        
        [path addQuadCurveToPoint:CGPointMake(minX+8, minY + cornerRadius + arrowWidth)
                     controlPoint:CGPointMake(minX+2, minY + cornerRadius + arrowWidth - 2)];
        
        [path addQuadCurveToPoint:CGPointMake(maxX, maxY)
                     controlPoint:CGPointMake(maxX-5, minY + cornerRadius + arrowWidth)];
        [path addLineToPoint:CGPointMake(maxX , minY)];
    }
    
    
    //    [path moveToPoint:CGPointMake(minX + cornerRadius, minY)];
    //    [path addLineToPoint:CGPointMake(maxX - cornerRadius, minY)];
    //    [path addQuadCurveToPoint:CGPointMake(maxX, minY + cornerRadius)
    //                 controlPoint:CGPointMake(maxX, minY)];
    //
    //    if (isLeft) {
    //        [path addLineToPoint:CGPointMake(maxX, midY - arrowHalf)];
    //        [path addLineToPoint:CGPointMake(maxX + arrowWidth, midY)];
    //        [path addLineToPoint:CGPointMake(maxX, midY + arrowHalf)];
    //    }
    //
    //    [path addLineToPoint:CGPointMake(maxX, maxY - cornerRadius)];
    //    [path addQuadCurveToPoint:CGPointMake(maxX - cornerRadius, maxY)
    //                 controlPoint:CGPointMake(maxX, maxY)];
    //    [path addLineToPoint:CGPointMake(minX + cornerRadius, maxY)];
    //    [path addQuadCurveToPoint:CGPointMake(minX, maxY - cornerRadius)
    //                 controlPoint:CGPointMake(minX, maxY)];
    //
    //    if (!isLeft) {
    //        [path addLineToPoint:CGPointMake(minX, midY + arrowHalf)];
    //        [path addLineToPoint:CGPointMake(minX - arrowWidth, midY)];
    //        [path addLineToPoint:CGPointMake(minX, midY - arrowHalf)];
    //    }
    //
    //    [path addLineToPoint:CGPointMake(minX, minY + cornerRadius)];
    //    [path addQuadCurveToPoint:CGPointMake(minX + cornerRadius, minY)
    //                 controlPoint:CGPointMake(minX, minY)];
    [path closePath];
    
    return path;
}

#pragma mark - 标注点聚合管理方法(叠罗汉)

/**
 * 处理地图标注点的聚合显示
 * 按照150米半径对标注点进行聚类，管理显示/隐藏状态
 */
- (void)processAnnotationClustering
{
    // 获取所有需要处理的标注点（排除用户位置）
    NSMutableArray *allAnnotations = [NSMutableArray array];
    for (XDXPointAnnotation *annotation in self.locations.allValues) {
        annotation.anns = [NSMutableArray array];
        annotation.isHide = NO;
        [self.mapView viewForAnnotation:annotation].alpha = 1;
        [allAnnotations addObject:annotation];
    }
    
    // 创建用户位置的数据字典（仅用于存储数据，不作为锚点）
    XDXPointAnnotation *userLocationData = [[XDXPointAnnotation alloc] init];
    if (self.mapView.userLocation) {
        userLocationData.userId = [XDXShareInstance shareInstance].userId;
        userLocationData.nickName = [XDXShareInstance shareInstance].nickName;
        userLocationData.avatar = [XDXShareInstance shareInstance].avatar;
        userLocationData.speed = [NSString stringWithFormat:@"%f", [XDXLocationManager shareInstance].lastLocation.speed < 0 ? 0 : ([XDXLocationManager shareInstance].lastLocation.speed * 3.6)];
        userLocationData.anns = [NSMutableArray array];
        userLocationData.battery = [NSString stringWithFormat:@"%.0f", [UIDevice currentDevice].batteryLevel * 100];
        userLocationData.isCharge = ([UIDevice currentDevice].batteryState == UIDeviceBatteryStateCharging) ?YES : NO;
    }
    [self.mapView viewForAnnotation:self.mapView.userLocation].alpha = 1;
    
    // 1. 处理聚类逻辑 - 按顺序取锚点（不包含用户位置）
    for (NSInteger i = 0; i < allAnnotations.count; i++) {
        XDXPointAnnotation *anchorAnnotation = allAnnotations[i];
        
        // 跳过已经是隐藏状态的标注点
        if (anchorAnnotation.isHide) {
            continue;
        }
        
        // 初始化锚点的anns数组
        if (!anchorAnnotation.anns) {
            anchorAnnotation.anns = [NSMutableArray array];
        }
        NSMutableArray *anchorAnns = anchorAnnotation.anns;
        
        // 查找150米半径内的其他标注点
        for (NSInteger j = 0; j < allAnnotations.count; j++) {
            if (i == j) continue; // 跳过自己
            
            XDXPointAnnotation *otherAnnotation = allAnnotations[j];
            
            // 计算距离（使用TrackTool的方法，返回km，转换为米）
            double distance = [TrackTool distanceBetweenOrderByLatitudeA:anchorAnnotation.coordinate.latitude
                                                               latitudeB:otherAnnotation.coordinate.latitude
                                                              longitudeA:anchorAnnotation.coordinate.longitude
                                                              longitudeB:otherAnnotation.coordinate.longitude] * 1000;
            
            // 如果在150米半径内
            if (distance <= 150) {
                // 将其他标注点添加到锚点的anns中
                if (![anchorAnns containsObject:otherAnnotation]) {
                    [anchorAnns addObject:otherAnnotation];
                    
                    for (NSInteger j = 0; j < allAnnotations.count; j++) {
                        if (j==i) {
                            continue;
                        }
                        if (((XDXPointAnnotation *)allAnnotations[j]).anns.count>0) {
                            for (XDXPointAnnotation *ann in ((XDXPointAnnotation *)allAnnotations[j]).anns) {
                                if (ann.userId.integerValue==otherAnnotation.userId.integerValue) {
                                    [((XDXPointAnnotation *)allAnnotations[j]).anns removeObject:ann];
                                    break;
                                }
                            }
                        }
                    }
                }
                
                // 设置其他标注点为隐藏状态
                otherAnnotation.isHide = YES;
                
                // 隐藏对应的CustomAnnotationView（使用alpha避免复用残留）
                CustomAnnotationView *otherAnnotationView = (CustomAnnotationView *)[self.mapView viewForAnnotation:otherAnnotation];
                if (otherAnnotationView) {
                    otherAnnotationView.alpha = 0.0;
                }
            }
        }
        
        // 检查是否将用户位置添加到当前锚点的anns中
        if (self.mapView.userLocation) {
            double distance = [TrackTool distanceBetweenOrderByLatitudeA:anchorAnnotation.coordinate.latitude
                                                               latitudeB:self.mapView.userLocation.coordinate.latitude
                                                              longitudeA:anchorAnnotation.coordinate.longitude
                                                              longitudeB:self.mapView.userLocation.coordinate.longitude] * 1000;
            
            // 如果用户位置在150米半径内，添加到锚点的anns中
            if (distance <= 150) {
                BOOL iscontainsUser = NO;
                for (XDXPointAnnotation *obj in anchorAnns) {
                    if (obj.userId.integerValue == [XDXShareInstance shareInstance].userId.integerValue) {
                        iscontainsUser = YES;
                        break;
                    }
                }
                
                if (iscontainsUser==NO) {
                    [anchorAnns addObject:userLocationData];
                    
                    for (NSInteger j = 0; j < allAnnotations.count; j++) {
                        if (j==i) {
                            continue;
                        }
                        if (((XDXPointAnnotation *)allAnnotations[j]).anns.count>0) {
                            for (XDXPointAnnotation *ann in ((XDXPointAnnotation *)allAnnotations[j]).anns) {
                                if (ann.userId.integerValue==userLocationData.userId.integerValue) {
                                    [((XDXPointAnnotation *)allAnnotations[j]).anns removeObject:ann];
                                    break;
                                }
                            }
                        }
                    }
                }
                
                // 隐藏用户位置对应的CustomAnnotationView（使用alpha避免复用残留）
                CustomAnnotationView *userLocationView = (CustomAnnotationView *)[self.mapView viewForAnnotation:self.mapView.userLocation];
                if (userLocationView) {
                    userLocationView.alpha = 0.0;
                }
            }
        }
    }
    
    
    
    // 返回anns发生变化的XDXPointAnnotation数组
    for (XDXPointAnnotation *annotation in allAnnotations) {
        CustomAnnotationView *annotationView = (CustomAnnotationView *)[self.mapView viewForAnnotation:annotation];
        NSDictionary *dict = @{@"nickName":annotation.nickName?annotation.nickName:@"",@"avatar":annotation.avatar?annotation.avatar:@"",@"battery":annotation.battery?annotation.battery:@"",@"speed":annotation.speed?annotation.speed:@"",@"activity":annotation.activity?annotation.activity:@"",@"isCharge":[NSString stringWithFormat:@"%d",annotation.isCharge]};
        [self loadCustomAnnotionViewWithDic:dict AnnotionView:annotationView];
    }
}

- (void)cluAnnotaionWithAnnotationView:(CustomAnnotationView *)annotationView Point:(XDXPointAnnotation *)point
{
    annotationView.view.hidden = YES;
    annotationView.portraitImageView.hidden = YES;
    annotationView.groupView.hidden = NO;
    annotationView.circle.hidden = YES;
    [annotationView.groupView setFrame:CGRectMake((kWidth-kGroupWidth)/2, 0, kGroupWidth, kPortraitHeight)];
    for (UIView *view in  annotationView.groupView.subviews) {
        [view removeFromSuperview];
    }
    
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kGroupWidth, kPortraitHeight+7)];
    [annotationView.groupView addSubview:view];
    
    CALayer *layer = [CALayer layer];
    layer.frame = view.bounds;
    
    layer.masksToBounds = NO;
    UIImage *img = [UIImage imageNamed:@"location_cor"];
    layer.contents      = (__bridge id)img.CGImage;
    layer.contentsScale = img.scale;                 // 或 [UIScreen mainScreen].scale
    layer.contentsGravity = kCAGravityResize;        // 确保按大小拉伸
    
    // 以“点”为单位定义不拉伸的四边
    CGFloat topCap    = kPortraitWidth;   // 上面 64pt 不拉伸
    CGFloat bottomCap = 0;
    CGFloat leftCap   = 0;
    CGFloat rightCap  = 0;
    
    // 用图片真实 size 来归一化
    CGFloat w = img.size.width;
    CGFloat h = img.size.height;
    layer.contentsCenter = CGRectMake(leftCap / w,
                                      topCap  / h,
                                      (w - leftCap - rightCap) / w,
                                      (h - topCap - bottomCap) / h);
    layer.shadowColor = RealBlackColor.CGColor;
    layer.shadowOffset = CGSizeMake(0,2);
    layer.shadowOpacity = 0.1;
    layer.shadowRadius = 3;
    [view.layer addSublayer:layer];
    
    
    UIImageView *selfImg = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kPortraitWidth, kPortraitHeight)];
    selfImg.userInteractionEnabled = YES;
    selfImg.layer.masksToBounds = YES;
    [selfImg.layer setCornerRadius:26];
    [selfImg.layer setBorderWidth:kHoriMargin];
    [selfImg.layer setBorderColor:RealWhiteColor.CGColor];
    selfImg.contentMode = UIViewContentModeScaleAspectFill;
    [selfImg sd_setImageWithURL:[NSURL URLWithString:point.avatar]];
    [view addSubview:selfImg];
    UITapGestureRecognizer *selfTap = [[UITapGestureRecognizer alloc] init];
    [[selfTap rac_gestureSignal] subscribeNext:^(id x) {
        for (NSMutableDictionary *dic in self.memberListView.memberList) {
            if ([dic[@"userId"] integerValue]==point.userId.integerValue) {
                if ([dic isKindOfClass:[NSDictionary class]]) {
                    self.memberListView.MemberInfoBlock(dic);
                }
                break;
            }
        }
    }];
    [selfImg addGestureRecognizer:selfTap];
    
    
    UIImageView *firstImg = [[UIImageView alloc] initWithFrame:CGRectMake(kGroupWidth-kPortraitWidth, 0, kPortraitWidth, kPortraitHeight)];
    firstImg.userInteractionEnabled = YES;
    firstImg.layer.masksToBounds = YES;
    [firstImg.layer setCornerRadius:26];
    [firstImg.layer setBorderWidth:kHoriMargin];
    [firstImg.layer setBorderColor:RealWhiteColor.CGColor];
    firstImg.contentMode = UIViewContentModeScaleAspectFill;
    [firstImg sd_setImageWithURL:[NSURL URLWithString:((XDXPointAnnotation *)point.anns.firstObject).avatar]];
    [view addSubview:firstImg];
    UITapGestureRecognizer *firstTap = [[UITapGestureRecognizer alloc] init];
    [[firstTap rac_gestureSignal] subscribeNext:^(id x) {
        NSInteger userInteger = ((XDXPointAnnotation *)point.anns.firstObject).userId.integerValue;
        for (NSMutableDictionary *dic in self.memberListView.memberList) {
            if ([dic[@"userId"] integerValue]==userInteger) {
                if ([dic isKindOfClass:[NSDictionary class]]) {
                    self.memberListView.MemberInfoBlock(dic);
                }
                break;
            }
        }
    }];
    [firstImg addGestureRecognizer:firstTap];
    
    if (point.anns.count>2) {
        [annotationView.groupView setFrame:CGRectMake((kWidth-kGroupWidth)/2, -(kGroupWidth-kPortraitHeight), kGroupWidth, kGroupWidth)];
        [view setFrame:CGRectMake(0, 0, kGroupWidth, kGroupWidth+7)];
        layer.frame = view.bounds;
        
        // 以“点”为单位定义不拉伸的四边
        CGFloat topCap    = 0;
        CGFloat bottomCap = 7;
        CGFloat leftCap   = 0;
        CGFloat rightCap  = 0;
        
        // 用图片真实 size 来归一化
        CGFloat w = img.size.width;
        CGFloat h = img.size.height;
        layer.contentsCenter = CGRectMake(leftCap / w,
                                          topCap  / h,
                                          (w - leftCap - rightCap) / w,
                                          (h - topCap - bottomCap) / h);
        
        selfImg.y = kGroupWidth-kPortraitHeight;
        firstImg.y = kGroupWidth-kPortraitHeight;
        
        for (int i=1; i < 3; i ++) {
            UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake((i-1)*(kGroupWidth-kPortraitWidth), 0, kPortraitWidth, kPortraitHeight)];
            img.userInteractionEnabled = YES;
            img.layer.masksToBounds = YES;
            [img.layer setCornerRadius:26];
            [img.layer setBorderWidth:kHoriMargin];
            [img.layer setBorderColor:RealWhiteColor.CGColor];
            img.contentMode = UIViewContentModeScaleAspectFill;
            [img sd_setImageWithURL:[NSURL URLWithString:((XDXPointAnnotation *)point.anns[i]).avatar]];
            [view addSubview:img];
            
            UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
            [[tap rac_gestureSignal] subscribeNext:^(id x) {
                NSInteger userInteger = ((XDXPointAnnotation *)point.anns[i]).userId.integerValue;
                for (NSMutableDictionary *dic in self.memberListView.memberList) {
                    if ([dic[@"userId"] integerValue]==userInteger) {
                        if ([dic isKindOfClass:[NSDictionary class]]) {
                            self.memberListView.MemberInfoBlock(dic);
                        }
                        break;
                    }
                }
            }];
            [img addGestureRecognizer:tap];
        }
    }else if (point.anns.count>1){
        [annotationView.groupView setFrame:CGRectMake((kWidth-kGroupWidth)/2, -(kGroupWidth-kPortraitHeight), kGroupWidth, kGroupWidth)];
        view.y = kGroupWidth-kPortraitHeight;
        UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake((kGroupWidth-kPortraitWidth)/2, 0, kPortraitWidth, kPortraitHeight)];
        img.userInteractionEnabled = YES;
        img.layer.masksToBounds = YES;
        [img.layer setCornerRadius:26];
        [img.layer setBorderWidth:kHoriMargin];
        [img.layer setBorderColor:RealWhiteColor.CGColor];
        img.contentMode = UIViewContentModeScaleAspectFill;
        [img sd_setImageWithURL:[NSURL URLWithString:((XDXPointAnnotation *)point.anns[1]).avatar]];
        [annotationView.groupView addSubview:img];
        
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
        [[tap rac_gestureSignal] subscribeNext:^(id x) {
            NSInteger userInteger = ((XDXPointAnnotation *)point.anns[1]).userId.integerValue;
            for (NSMutableDictionary *dic in self.memberListView.memberList) {
                if ([dic[@"userId"] integerValue]==userInteger) {
                    if ([dic isKindOfClass:[NSDictionary class]]) {
                        self.memberListView.MemberInfoBlock(dic);
                    }
                    break;
                }
            }
        }];
        
        [img addGestureRecognizer:tap];
    }
}

#pragma mark - Regions本地化存储方法
// 保存regions到plist文件
- (void)saveRegionsToPlist
{
    if (!self.memberListView.regions) {
        return;
    }
    
    // 获取Documents目录路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"Regions.plist"];
    
    // 将regions转换为可序列化的格式
    NSMutableArray *serializableArray = [NSMutableArray array];
    for (NSDictionary *region in self.memberListView.regions) {
        NSMutableDictionary *serializableRegion = [NSMutableDictionary dictionaryWithDictionary:region];
        // 确保所有数据都是可序列化的
        [serializableArray addObject:serializableRegion];
    }
    
    // 写入plist文件
    BOOL success = [serializableArray writeToFile:plistPath atomically:YES];
    if (success) {
        [[NSUserDefaults standardUserDefaults] setValue:[XDXTimeTool getNowTimeTimestamp] forKey:@"regionsTime"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
}

// 从plist文件读取regions
- (void)loadRegionsFromPlist
{
    // 获取Documents目录路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"Regions.plist"];
    
    // 检查文件是否存在
    if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
        // 从plist文件读取数据
        NSArray *loadedArray = [NSArray arrayWithContentsOfFile:plistPath];
        if (loadedArray) {
            self.memberListView.regions = [NSMutableArray arrayWithArray:loadedArray];
        } else {
            self.memberListView.regions = [NSMutableArray array];
        }
    } else {
        self.memberListView.regions = [NSMutableArray array];
    }
}

#pragma mark - 群组数据同步方法
// 同步更新当前群组信息和全局群组列表
- (void)syncGroupDataWithMemberList
{
    if (!self.groupInfo[@"id"] || !self.memberListView.memberList) {
        return;
    }
    
    // 更新当前群组信息
    [self.groupInfo setValue:[NSMutableArray arrayWithArray:self.memberListView.memberList] forKey:@"memberList"];
    
    // 更新全局群组列表中对应群组的数据
    [self updateGroupListWithCurrentGroupInfo];
    
    // 本地化存储群组列表到plist文件
    [self saveGroupListToPlist];
    
}

// 更新全局群组列表中对应群组的数据
- (void)updateGroupListWithCurrentGroupInfo
{
    if (!self.groupList || !self.groupInfo[@"id"]) {
        return;
    }
    
    NSString *currentGroupId = [NSString stringWithFormat:@"%@", [XDXShareInstance shareInstance].groupId];
    
    for (NSInteger i = 0; i < self.groupList.count; i++) {
        NSMutableDictionary *group = [NSMutableDictionary dictionaryWithDictionary:self.groupList[i]];
        if ([group[@"id"] integerValue]==currentGroupId.integerValue) {
            // 更新匹配的群组数据
            [group setValue:[NSMutableArray arrayWithArray:self.memberListView.memberList] forKey:@"memberList"];
            [group setValue:self.groupInfo[@"name"] forKey:@"name"];
            // 可以根据需要更新其他字段，如最后更新时间等
            [group setValue:[XDXTimeTool currentDate] forKey:@"lastUpdateTime"];
            
            // 替换原数组中的对象
            [self.groupList replaceObjectAtIndex:i withObject:group];
            break;
        }
    }
}

// 保存群组列表到plist文件
- (void)saveGroupListToPlist
{
    if (!self.groupList) {
        return;
    }
    
    // 获取Documents目录路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"GroupList.plist"];
    
    // 将群组列表转换为可序列化的格式
    NSMutableArray *serializableArray = [NSMutableArray array];
    for (NSDictionary *group in self.groupList) {
        NSMutableDictionary *serializableGroup = [NSMutableDictionary dictionary];
        for (NSString *key in group.allKeys) {
            if (![group[key] isKindOfClass:[NSNull class]] && group[key]) {
                [serializableGroup setValue:group[key] forKey:key];
            }
        }
        // 确保所有数据都是可序列化的
        [serializableArray addObject:serializableGroup];
    }
    
    // 写入plist文件
    BOOL success = [serializableArray writeToFile:plistPath atomically:YES];
    if (success) {
        [[NSUserDefaults standardUserDefaults] setValue:[XDXTimeTool getNowTimeTimestamp] forKey:GroupListTime];
        [[NSUserDefaults standardUserDefaults] synchronize];
        
    }
}

// 从plist文件读取群组列表
- (void)loadGroupListFromPlist
{
    // 获取Documents目录路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"GroupList.plist"];
    
    // 检查文件是否存在
    if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
        // 从plist文件读取数据
        NSArray *loadedArray = [NSArray arrayWithContentsOfFile:plistPath];
        if (loadedArray) {
            self.groupList = [NSMutableArray arrayWithArray:loadedArray];
            // 根据保存的groupId初始化当前群组信息
            [self initializeGroupInfoFromLoadedData];
        } else {
            self.groupList = [NSMutableArray array];
        }
    } else {
        self.groupList = [NSMutableArray array];
    }
}

// 根据保存的groupId从加载的数据中初始化当前群组信息
- (void)initializeGroupInfoFromLoadedData
{
    if (!self.groupList || self.groupList.count == 0) {
        return;
    }
    
    // 获取保存的群组ID
    NSString *savedGroupId = [[NSUserDefaults standardUserDefaults] objectForKey:GroupId];
    if (!savedGroupId || savedGroupId.integerValue == 0) {
        // 如果没有保存的群组ID，使用第一个群组
        if (self.groupList.count > 0) {
            self.groupInfo = [NSMutableDictionary dictionaryWithDictionary:self.groupList[0]];
            [XDXShareInstance shareInstance].groupId = self.groupInfo[@"id"];
            [[NSUserDefaults standardUserDefaults] setValue:self.groupInfo[@"id"] forKey:GroupId];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [self setRoom];
            [self loadMemberListFromGroupInfo];
        }
        return;
    }
    
    // 在群组列表中查找匹配的群组
    BOOL foundGroup = NO;
    for (NSDictionary *group in self.groupList) {
        if ([group[@"id"] integerValue]==savedGroupId.integerValue) {
            // 找到匹配的群组，初始化groupInfo
            self.groupInfo = [NSMutableDictionary dictionaryWithDictionary:group];
            [XDXShareInstance shareInstance].groupId = self.groupInfo[@"id"];
            [[NSUserDefaults standardUserDefaults] setValue:self.groupInfo[@"id"] forKey:GroupId];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [self setRoom];
            
            foundGroup = YES;
            break;
        }
    }
    
    if (foundGroup) {
        // 加载成员列表并刷新界面
        [self loadMemberListFromGroupInfo];
    } else {
        // 如果没找到匹配的群组，使用第一个群组
        if (self.groupList.count > 0) {
            self.groupInfo = [NSMutableDictionary dictionaryWithDictionary:self.groupList[0]];
            [XDXShareInstance shareInstance].groupId = self.groupInfo[@"id"];
            [[NSUserDefaults standardUserDefaults] setValue:self.groupInfo[@"id"] forKey:GroupId];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [self setRoom];
            [self loadMemberListFromGroupInfo];
        }
    }
}

// 从groupInfo中加载成员列表数据到memberListView
- (void)loadMemberListFromGroupInfo
{
    if (!self.groupInfo) {
        return;
    }
    
    // 从groupInfo中获取成员列表
    NSArray *memberList = self.groupInfo[@"memberList"];
    if (memberList && [memberList isKindOfClass:[NSArray class]]) {
        // 初始化memberListView的成员列表
        self.memberListView.memberList = [NSMutableArray arrayWithArray:memberList];
        
        NSInteger groupListTime = [[[NSUserDefaults standardUserDefaults] objectForKey:GroupListTime] integerValue];
        
        if (([XDXTimeTool getNowTimeTimestamp].integerValue-groupListTime)>=21600) {
            for (NSMutableDictionary *user in memberList) {
                [user setValue:@"" forKey:@"lastlog"];
            }
        }
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (self.locations.allValues.count==0) {
                for (NSMutableDictionary *dic in memberList) {
                    // 添加新用户时，只需要添加地图中没有添加过的新用户，其余用户不用添加
                    if ([dic[@"userId"] integerValue]!=[XDXShareInstance shareInstance].userId.integerValue) {
                        [self addAnnotationWithInfo:dic];
                    }
                }
            }
        });
        // 刷新memberListView
        [self.memberListView.tableView reloadData];
    } else {
        // 如果没有成员列表数据，初始化为空数组
        self.memberListView.memberList = [NSMutableArray array];
        [self.memberListView.tableView reloadData];
    }
}

// 智能更新群组列表
- (void)smartUpdateGroupListWithResponseData:(NSArray *)responseData
{
    if (!responseData || ![responseData isKindOfClass:[NSArray class]]) {
        return;
    }
    
    // 如果groupList未初始化，直接赋值
    if (!self.groupList) {
        self.groupList = [NSMutableArray arrayWithArray:responseData];
        return;
    }
    
    // 创建响应数据的ID集合，用于快速查找
    NSMutableSet *responseIds = [NSMutableSet set];
    for (NSDictionary *group in responseData) {
        [responseIds addObject:@([group[@"id"] integerValue])];
    }
    
    // 创建本地数据的ID集合
    NSMutableSet *localIds = [NSMutableSet set];
    for (NSDictionary *group in self.groupList) {
        [localIds addObject:@([group[@"id"] integerValue])];
    }
    
    // 1. 更新已存在的群组（只更新name和memberCount字段）
    for (NSInteger i = 0; i < self.groupList.count; i++) {
        NSMutableDictionary *localGroup = [NSMutableDictionary dictionaryWithDictionary:self.groupList[i]];
        NSInteger localGroupId = [localGroup[@"id"] integerValue];
        
        // 在响应数据中查找匹配的群组
        NSDictionary *matchingResponseGroup = nil;
        for (NSDictionary *responseGroup in responseData) {
            if ([responseGroup[@"id"] integerValue] == localGroupId) {
                matchingResponseGroup = responseGroup;
                break;
            }
        }
        
        if (matchingResponseGroup) {
            // 更新name和memberCount字段
            if (matchingResponseGroup[@"name"]) {
                [localGroup setValue:matchingResponseGroup[@"name"] forKey:@"name"];
            }
            if (matchingResponseGroup[@"memberCount"]) {
                [localGroup setValue:matchingResponseGroup[@"memberCount"] forKey:@"memberCount"];
            }
            if ([matchingResponseGroup[@"membership"] isKindOfClass:[NSDictionary class]]) {
                [localGroup setValue:matchingResponseGroup[@"membership"] forKey:@"membership"];
            }else{
                [localGroup removeObjectForKey:@"membership"];
            }
            
            // 替换原数组中的对象
            [self.groupList replaceObjectAtIndex:i withObject:localGroup];
        }
    }
    
    // 2. 删除本地存在但响应中不存在的群组
    NSMutableArray *groupsToRemove = [NSMutableArray array];
    for (NSDictionary *localGroup in self.groupList) {
        NSInteger localGroupId = [localGroup[@"id"] integerValue];
        if (![responseIds containsObject:@(localGroupId)]) {
            [groupsToRemove addObject:localGroup];
        }
    }
    [self.groupList removeObjectsInArray:groupsToRemove];
    
    // 3. 添加响应中存在但本地不存在的群组
    for (NSDictionary *responseGroup in responseData) {
        NSInteger responseGroupId = [responseGroup[@"id"] integerValue];
        if (![localIds containsObject:@(responseGroupId)]) {
            [self.groupList addObject:[NSMutableDictionary dictionaryWithDictionary:responseGroup]];
        }
    }
    
}

// 智能更新成员列表
- (void)smartUpdateMemberListWithResponseData:(NSArray *)responseData
{
    if (!responseData || ![responseData isKindOfClass:[NSArray class]]) {
        return;
    }
    
    // 如果memberListView.memberList未初始化，直接赋值
    if (!self.memberListView.memberList) {
        self.memberListView.memberList = [NSMutableArray arrayWithArray:responseData];
        return;
    }
    
    // 创建响应数据的userId集合，用于快速查找
    NSMutableSet *responseUserIds = [NSMutableSet set];
    for (NSDictionary *user in responseData) {
        [responseUserIds addObject:@([user[@"userId"] integerValue])];
    }
    
    // 创建本地数据的userId集合
    NSMutableSet *localUserIds = [NSMutableSet set];
    for (NSDictionary *user in self.memberListView.memberList) {
        [localUserIds addObject:@([user[@"userId"] integerValue])];
    }
    
    // 1. 更新已存在的成员（只更新remark、nickName、avatar字段）
    for (NSInteger i = 0; i < self.memberListView.memberList.count; i++) {
        NSMutableDictionary *localUser = [NSMutableDictionary dictionaryWithDictionary:self.memberListView.memberList[i]];
        NSInteger localUserId = [localUser[@"userId"] integerValue];
        
        // 在响应数据中查找匹配的成员
        NSDictionary *matchingResponseUser = nil;
        for (NSDictionary *responseUser in responseData) {
            if ([responseUser[@"userId"] integerValue] == localUserId) {
                matchingResponseUser = responseUser;
                break;
            }
        }
        
        if (matchingResponseUser) {
            // 更新remark、nickName、avatar字段
            if (matchingResponseUser[@"remark"]) {
                [localUser setValue:matchingResponseUser[@"remark"] forKey:@"remark"];
            }
            if (matchingResponseUser[@"nickName"]) {
                [localUser setValue:matchingResponseUser[@"nickName"] forKey:@"nickName"];
            }
            if (matchingResponseUser[@"avatar"]) {
                [localUser setValue:matchingResponseUser[@"avatar"] forKey:@"avatar"];
            }
            
            // 替换原数组中的对象
            [self.memberListView.memberList replaceObjectAtIndex:i withObject:localUser];
        }
    }
    
    // 2. 删除本地存在但响应中不存在的成员
    NSMutableArray *usersToRemove = [NSMutableArray array];
    for (NSDictionary *localUser in self.memberListView.memberList) {
        NSInteger localUserId = [localUser[@"userId"] integerValue];
        if (![responseUserIds containsObject:@(localUserId)]) {
            [usersToRemove addObject:localUser];
        }
    }
    [self.memberListView.memberList removeObjectsInArray:usersToRemove];
    
    // 3. 添加响应中存在但本地不存在的成员
    for (NSDictionary *responseUser in responseData) {
        NSInteger responseUserId = [responseUser[@"userId"] integerValue];
        if (![localUserIds containsObject:@(responseUserId)]) {
            [self.memberListView.memberList addObject:[NSMutableDictionary dictionaryWithDictionary:responseUser]];
        }
    }
}

@end

